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()

    _, 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)
    announce_gadget(q, stream, disco_event.stanza)

    handles = {}

    handles['alice'] = conn.RequestHandles(1, ['alice@localhost'])[0]

    # Alice, one our friends changed her properties
    send_buddy_changed_properties_msg(stream, 'alice@localhost',
            {'color': ('str', '#005FE4,#00A0FF')})

    event = q.expect('dbus-signal', signal='PropertiesChanged',
            args=[handles['alice'], {'color' : '#005FE4,#00A0FF'}])
def test(q, bus, conn, stream):
    conn.Connect()

    handles = {}

    _, 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)
    announce_gadget(q, stream, disco_event.stanza)

    activity_prop_iface = dbus.Interface(conn,
            'org.laptop.Telepathy.ActivityProperties')
    buddy_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')

    sync_stream(q, stream)

    # request 3 random activities (view 0)
    view_path = request_random_activity_view(q, stream, conn, 3, '1',
            [('activity1', '*****@*****.**',
                {'color': ('str', '#005FE4,#00A0FF')},
                [('lucien@localhost', {'color': ('str', '#AABBCC,#CCBBAA')}),
                 ('jean@localhost', {})]),])

    view0 = bus.get_object(conn.bus_name, view_path)
    view0_iface = dbus.Interface(view0, 'org.laptop.Telepathy.View')

    # Gadget is restarted so send us a new presence stanza
    presence = elem('presence', from_='gadget.localhost', to='test@localhost')
    stream.send(presence)

    q.expect('dbus-signal', signal='Closed', interface=cs.CHANNEL)
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)
    announce_gadget(q, stream, disco_event.stanza)

    act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties')
    buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    simple_presence_iface = dbus.Interface(conn, 'org.freedesktop.Telepathy.Connection.Interface.SimplePresence')

    q.expect('dbus-signal', signal='GadgetDiscovered')
    gadget_publish(q, stream, conn, True)

    # join a room
    room_handle, room_path = join_channel('*****@*****.**',
            q, conn, stream)

    call_async (q, buddy_info_iface, 'SetActivities', [("roomid", room_handle)])

    # pubsub activity iq
    event = q.expect('stream-iq', iq_type='set', query_name='pubsub',
        query_ns=ns.PUBSUB)
    acknowledge_iq(stream, event.stanza)

    event = q.expect('dbus-return', method='SetActivities')

    # make activity public
    call_async(q, act_prop_iface, 'SetProperties',
            1, {'title': 'My test activity', 'private': False})

    # pseudo invite
    event = q.expect('stream-message', to='gadget.localhost')
    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'] == 'roomid'

    # invite
    event = q.expect('stream-message', to='*****@*****.**')
    message = event.stanza
    x = xpath.queryForNodes('/message/x', message)
    assert (x is not None and len(x) == 1), repr(x)
    assert x[0].uri == ns.MUC_USER

    invites = xpath.queryForNodes('/x/invite', x[0])
    assert (invites is not None and len(invites) == 1), repr(invites)
    assert invites[0]['to'] == 'gadget.localhost'

    # pubsub activity prop iq
    event = q.expect('stream-iq')
    acknowledge_iq(stream, event.stanza)

    # pubsub activity iq
    event = q.expect('stream-iq')
    acknowledge_iq(stream, event.stanza)

    event = q.expect('dbus-return', method='SetProperties')

    # Gadget joins the room
    stream.send(make_muc_presence('none', 'participant', '*****@*****.**',
        'inspector', 'gadget.localhost'))

    muc = bus.get_object(conn.bus_name, room_path)
    muc_group = dbus.Interface(muc, "org.freedesktop.Telepathy.Channel.Interface.Group")

    sync_stream(q, stream)
    members = muc_group.GetMembers()
    assert conn.InspectHandles(1, members) == ['[email protected]/test']

    # Regression test for a nasty bug caused by the presence cache handling
    # the inspector presence as a non-MUC one because the inspector is not
    # added to MUC's members.
    handle = conn.RequestHandles(1, ['*****@*****.**'])[0]
    presence = simple_presence_iface.GetPresences([handle])
    assert presence[handle] == (7, 'unknown', '')

    # PEP activity update
    disconnect_conn(q, conn, stream, [EventPattern('stream-iq')])[0]
def test(q, bus, conn, stream):
    conn.Connect()

    handles = {}

    _, 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)

    activity_prop_iface = dbus.Interface(conn,
            'org.laptop.Telepathy.ActivityProperties')
    buddy_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')
    requests_iface = dbus.Interface(conn, cs.CONN_IFACE_REQUESTS)

    # Gadget was not announced yet
    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.ActivityView',
            'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
          })

    event = q.expect('dbus-error', method='CreateChannel')
    announce_gadget(q, stream, disco_event.stanza)
    sync_stream(q, stream)

    # check if we can request Activity views
    properties = conn.GetAll(
        cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE)

    assert ({cs.CHANNEL_TYPE:
            olpc_name_prefix + '.Channel.Type.ActivityView'},

            [olpc_name_prefix + '.Channel.Interface.View.MaxSize',
             olpc_name_prefix + '.Channel.Type.ActivityView.Properties',
             olpc_name_prefix + '.Channel.Type.ActivityView.Participants'],
         ) in properties.get('RequestableChannelClasses'),\
                 properties['RequestableChannelClasses']

    # request 3 random activities (view 1)
    view_path = request_random_activity_view(q, stream, conn, 3, '1',
            [('activity1', '*****@*****.**',
                {'color': ('str', '#005FE4,#00A0FF')},
                [('lucien@localhost', {'color': ('str', '#AABBCC,#CCBBAA')}),
                 ('jean@localhost', {})]),])

    view1 = bus.get_object(conn.bus_name, view_path)

    # check org.freedesktop.Telepathy.Channel D-Bus properties
    props = view1.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['ChannelType'] == 'org.laptop.Telepathy.Channel.Type.ActivityView'
    assert 'org.laptop.Telepathy.Channel.Interface.View' in props['Interfaces']
    assert props['TargetHandle'] == 0
    assert props['TargetID'] == ''
    assert props['TargetHandleType'] == 0

    # check org.laptop.Telepathy.Channel.Interface.View D-Bus properties
    props = view1.GetAll(
        'org.laptop.Telepathy.Channel.Interface.View',
        dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['MaxSize'] == 3

    # check org.laptop.Telepathy.Channel.Type.ActivityView D-Bus properties
    props = view1.GetAll(
        'org.laptop.Telepathy.Channel.Type.ActivityView',
        dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['Properties'] == {}
    assert props['Participants'] == []

    assert view1.GetChannelType(dbus_interface=cs.CHANNEL) ==\
            'org.laptop.Telepathy.Channel.Type.ActivityView'

    ## Current views ##
    # view 1: activity 1 (with: Lucien, Jean)

    handles['lucien'], handles['jean'] = \
            conn.RequestHandles(1, ['lucien@localhost', 'jean@localhost'])

    event = q.expect('dbus-signal', signal='ActivityPropertiesChanged')
    handles['room1'], props = event.args
    assert conn.InspectHandles(2, [handles['room1']])[0] == \
            '*****@*****.**'
    assert props == {'color': '#005FE4,#00A0FF'}

    q.expect('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.Channel.Interface.View',
            args=[[('activity1', handles['room1'])], []])

    # participants are added to view
    q.expect('dbus-signal', signal='BuddiesChanged',
            args=[[handles['lucien'], handles['jean']], []])

    # participants are added to activity
    q.expect_many(
        EventPattern('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['lucien'], [('activity1', handles['room1'])]]),
        EventPattern('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['jean'], [('activity1', handles['room1'])]]))

    # check activities and buddies in view
    check_view(view1, conn, [('activity1', handles['room1'])],
            ['lucien@localhost', 'jean@localhost'])

    # we can now get activity properties
    props = activity_prop_iface.GetProperties(handles['room1'])
    assert props == {'color': '#005FE4,#00A0FF'}

    # and we can get participant's properties too
    props = buddy_prop_iface.GetProperties(handles['lucien'])
    assert props == {'color': '#AABBCC,#CCBBAA'}

    # and their activities
    call_async (q, buddy_prop_iface, 'GetActivities', handles['lucien'])

    event = q.expect('stream-iq', to='lucien@localhost', query_name='pubsub',
            query_ns=ns.PUBSUB)
    # return an error, we can't query pubsub node
    answer_error_to_pubsub_request(stream, event.stanza)

    q.expect('dbus-return', method='GetActivities',
            value=([('activity1', handles['room1'])],))

    # activity search by properties (view 2)
    props = dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')

    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.ActivityView',
            'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
            'org.laptop.Telepathy.Channel.Type.ActivityView.Properties': props,
          })

    iq_event, return_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_ACTIVITY),
        EventPattern('dbus-return', method='CreateChannel'))

    properties_nodes = xpath.queryForNodes('/iq/view/activity/properties',
            iq_event.stanza)
    props = parse_properties(properties_nodes[0])
    assert props == {'color': ('str', '#AABBCC,#001122')}

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '2'
    assert view['size'] == '5'

    send_reply_to_activity_view_request(stream, iq_event.stanza,
            [('activity2', '*****@*****.**',
                {'color': ('str', '#AABBCC,#001122')}, [])])

    ## Current views ##
    # view 1: activity 1 (with: Lucien, Jean)
    # view 2: activity 2

    view_path = return_event.value[0]
    view2 = bus.get_object(conn.bus_name, view_path)

    props = return_event.value[1]
    assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Properties'] == \
            {'color': '#AABBCC,#001122'}
    assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Participants'] == []

    event = q.expect('dbus-signal', signal='ActivityPropertiesChanged')
    handles['room2'], props = event.args
    assert conn.InspectHandles(2, [handles['room2']])[0] == '*****@*****.**'
    assert props == {'color': '#AABBCC,#001122'}

    q.expect('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.Channel.Interface.View',
            args=[[('activity2', handles['room2'])], []])

    act = view2.Get(olpc_name_prefix + '.Channel.Interface.View',
        'Activities', dbus_interface=dbus.PROPERTIES_IFACE)
    assert sorted(act) == [('activity2', handles['room2'])]

    buddies = view2.Get(olpc_name_prefix + '.Channel.Interface.View',
        'Buddies', dbus_interface=dbus.PROPERTIES_IFACE)
    assert buddies == []

    # activity search by participants (view 3)
    participants = conn.RequestHandles(1, ["alice@localhost", "bob@localhost"])

    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.ActivityView',
            'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
            'org.laptop.Telepathy.Channel.Type.ActivityView.Participants': participants,
          })

    iq_event, return_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_ACTIVITY),
        EventPattern('dbus-return', method='CreateChannel'))

    buddies = xpath.queryForNodes('/iq/view/activity/buddy', iq_event.stanza)
    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '3'
    assert view['size'] == '5'
    assert len(buddies) == 2
    assert (buddies[0]['jid'], buddies[1]['jid']) == ('alice@localhost',
            'bob@localhost')

    send_reply_to_activity_view_request(stream, iq_event.stanza,
            [('activity3', '*****@*****.**',
                {'color': ('str', '#AABBCC,#001122')}, [])])

    ## Current views ##
    # view 1: activity 1 (with: Lucien, Jean)
    # view 2: activity 2
    # view 3: activity 3

    view_path = return_event.value[0]
    view3 = bus.get_object(conn.bus_name, view_path)

    event = q.expect('dbus-signal', signal='ActivityPropertiesChanged')
    handles['room3'], props = event.args
    assert conn.InspectHandles(2, [handles['room3']])[0] == '*****@*****.**'
    assert props == {'color': '#AABBCC,#001122'}

    q.expect('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.Channel.Interface.View',
            args=[[('activity3', handles['room3'])], []])

    act = view3.Get(olpc_name_prefix + '.Channel.Interface.View',
        'Activities',
        dbus_interface=dbus.PROPERTIES_IFACE)
    assert sorted(act) == [('activity3', handles['room3'])]

    # add activity 4 to view 1
    message = create_gadget_message('alice@localhost')

    added = message.addElement((ns.OLPC_ACTIVITY, 'added'))
    added['id'] = '1'
    activity = added.addElement((None, 'activity'))
    activity['id'] = 'activity4'
    activity['room'] = '*****@*****.**'
    properties = activity.addElement((ns.OLPC_ACTIVITY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#DDEEDD,#EEDDEE')}):
        properties.addChild(node)
    buddy = activity.addElement((None, 'buddy'))
    buddy['jid'] = 'fernand@localhost'
    properties = buddy.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#AABBAA,#BBAABB')}):
        properties.addChild(node)
    buddy = activity.addElement((None, 'buddy'))
    buddy['jid'] = 'jean@localhost'

    stream.send(message)

    ## Current views ##
    # view 1: activity 1 (with: Lucien, Jean), activity 4 (with: Fernand, Jean)
    # view 2: activity 2
    # view 3: activity 3
    # participants are added to view

    handles['fernand'] = conn.RequestHandles(1, ['fernand@localhost',])[0]

    # activity is added
    event = q.expect('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.Channel.Interface.View')
    added, removed = event.args
    assert len(added) == 1
    id, handles['room4'] = added[0]
    assert id == 'activity4'
    assert sorted(conn.InspectHandles(2, [handles['room4']])) == \
            ['*****@*****.**']

    # buddies are added to view
    q.expect('dbus-signal', signal='BuddiesChanged',
            args=[[handles['fernand'], handles['jean']], []])

    # buddies are added to activity
    q.expect_many(
        EventPattern('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['fernand'], [('activity4', handles['room4'])]]),
        EventPattern('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['jean'], [('activity1', handles['room1']),
                ('activity4', handles['room4'])]]))

    # check activities and buddies in view
    check_view(view1, conn, [
        ('activity1', handles['room1']), ('activity4', handles['room4'])],
        ['fernand@localhost', 'lucien@localhost', 'jean@localhost'])

    # check activity's properties
    props = activity_prop_iface.GetProperties(handles['room4'])
    assert props == {'color': '#DDEEDD,#EEDDEE'}

    # Gadget informs us about an activity properties change
    message = create_gadget_message('alice@localhost')

    change = message.addElement((ns.OLPC_ACTIVITY, 'change'))
    change['activity'] = 'activity1'
    change['room'] = '*****@*****.**'
    change['id'] = '1'
    properties = change.addElement((ns.OLPC_ACTIVITY_PROPS, 'properties'))
    for node in properties_to_xml({'tags': ('str', 'game'), \
            'color': ('str', '#AABBAA,#BBAABB')}):
        properties.addChild(node)

    stream.send(message)

    q.expect('dbus-signal', signal='ActivityPropertiesChanged',
            args=[handles['room1'], {'tags': 'game', 'color': '#AABBAA,#BBAABB'}])

    # we now get the new activity properties
    props = activity_prop_iface.GetProperties(handles['room1'])
    assert props == {'tags': 'game', 'color': '#AABBAA,#BBAABB'}

    # Marcel joined activity 1
    message = create_gadget_message('alice@localhost')

    activity = message.addElement((ns.OLPC_ACTIVITY, 'activity'))
    activity['room'] = '*****@*****.**'
    activity['view'] = '1'
    joined = activity.addElement((None, 'joined'))
    joined['jid'] = 'marcel@localhost'
    properties = joined.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#CCCCCC,#DDDDDD')}):
        properties.addChild(node)

    stream.send(message)

    ## Current views ##
    # view 1: activity 1 (with: Lucien, Jean, Marcel), activity 4 (with
    # Fernand, Jean)
    # view 2: activity 2
    # view 3: activity 3

    handles['marcel'] = conn.RequestHandles(1, ['marcel@localhost',])[0]

    q.expect_many(
            EventPattern('dbus-signal', signal='BuddiesChanged',
                args=[[handles['marcel']], []]),
            EventPattern('dbus-signal', signal='PropertiesChanged',
                args=[handles['marcel'], {'color': '#CCCCCC,#DDDDDD'}]),
            EventPattern('dbus-signal', signal='ActivitiesChanged',
                interface='org.laptop.Telepathy.BuddyInfo',
                args=[handles['marcel'], [('activity1', handles['room1'])]]))

    # check activities and buddies in view
    check_view(view1, conn, [
        ('activity1', handles['room1']),('activity4', handles['room4'])],
        ['fernand@localhost', 'lucien@localhost', 'jean@localhost',
            'marcel@localhost'])

    # Marcel left activity 1
    message = create_gadget_message('alice@localhost')

    activity = message.addElement((ns.OLPC_ACTIVITY, 'activity'))
    activity['room'] = '*****@*****.**'
    activity['view'] = '1'
    left = activity.addElement((None, 'left'))
    left['jid'] = 'marcel@localhost'

    stream.send(message)

    ## Current views ##
    # view 1: activity 1 (with: Lucien, Jean), activity 4 (with Fernand, Jean)
    # view 2: activity 2
    # view 3: activity 3

    q.expect_many(
            EventPattern('dbus-signal', signal='BuddiesChanged',
                args=[[], [handles['marcel']]]),
            EventPattern('dbus-signal', signal='ActivitiesChanged',
                interface='org.laptop.Telepathy.BuddyInfo',
                args=[handles['marcel'], []]))

    # check activities and buddies in view
    check_view(view1, conn, [
        ('activity1', handles['room1']),('activity4', handles['room4'])],
        ['fernand@localhost', 'lucien@localhost', 'jean@localhost'])

    # Jean left activity 1
    message = create_gadget_message('alice@localhost')

    activity = message.addElement((ns.OLPC_ACTIVITY, 'activity'))
    activity['room'] = '*****@*****.**'
    activity['view'] = '1'
    left = activity.addElement((None, 'left'))
    left['jid'] = 'jean@localhost'

    stream.send(message)

    ## Current views ##
    # view 1: activity 1 (with: Lucien), activity 4 (with Fernand, Jean)
    # view 2: activity 2
    # view 3: activity 3

    q.expect('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['jean'], [('activity4', handles['room4'])]])

    # Jean wasn't removed from the view as he is still in activity 4
    check_view(view1, conn, [
        ('activity1', handles['room1']),('activity4', handles['room4'])],
        ['fernand@localhost', 'lucien@localhost', 'jean@localhost'])

    # remove activity 1 from view 1
    message = create_gadget_message('alice@localhost')

    removed = message.addElement((ns.OLPC_ACTIVITY, 'removed'))
    removed['id'] = '1'
    activity = removed.addElement((None, 'activity'))
    activity['id'] = 'activity1'
    activity['room'] = '*****@*****.**'

    stream.send(message)

    ## Current views ##
    # view 1: activity 4 (with Jean, Fernand)
    # view 2: activity 2
    # view 3: activity 3

    q.expect_many(
    # participants are removed from the view
            EventPattern('dbus-signal', signal='BuddiesChanged',
                args=[[], [handles['lucien']]]),
    # activity is removed from the view
            EventPattern('dbus-signal', signal='ActivitiesChanged',
                interface='org.laptop.Telepathy.Channel.Interface.View',
                args=[[], [('activity1', handles['room1'])]]),
            EventPattern('dbus-signal', signal='ActivitiesChanged',
                interface='org.laptop.Telepathy.BuddyInfo',
                args=[handles['lucien'], []]))

    # check activities and buddies in view
    check_view(view1, conn, [
        ('activity4', handles['room4'])],
        ['fernand@localhost', 'jean@localhost'])

    # close view 1
    call_async(q, view1, 'Close')
    event_msg, _, _, _ = q.expect_many(
        EventPattern('stream-message', to='gadget.localhost'),
        EventPattern('dbus-return', method='Close'),
        # Jean and Fernand left activity4
        EventPattern('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['jean'], []]),
        EventPattern('dbus-signal', signal='ActivitiesChanged',
            interface='org.laptop.Telepathy.BuddyInfo',
            args=[handles['fernand'], []]))

    close = xpath.queryForNodes('/message/close', event_msg.stanza)
    assert len(close) == 1
    assert close[0]['id'] == '1'

    close_view(q, view2, '2')

    close_view(q, view3, '3')

    # View request without MaxSize property
    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.ActivityView',
          })

    event = q.expect('dbus-error', method='CreateChannel')
    assert event.error.get_dbus_name() == cs.INVALID_ARGUMENT

    # test participants and properties search
    props = dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
    participants = conn.RequestHandles(1, ["alice@localhost", "bob@localhost"])

    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.ActivityView',
            'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
            'org.laptop.Telepathy.Channel.Type.ActivityView.Properties': props,
            'org.laptop.Telepathy.Channel.Type.ActivityView.Participants': participants,
          })

    iq_event, return_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost', query_ns=ns.OLPC_ACTIVITY),
        EventPattern('dbus-return', method='CreateChannel'))

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '4'
    assert view['size'] == '5'

    properties_nodes = xpath.queryForNodes('/iq/view/activity/properties',
            iq_event.stanza)
    props = parse_properties(properties_nodes[0])
    assert props == {'color': ('str', '#AABBCC,#001122')}

    buddies = xpath.queryForNodes('/iq/view/activity/buddy', iq_event.stanza)
    assert len(buddies) == 2
    assert (buddies[0]['jid'], buddies[1]['jid']) == ('alice@localhost',
            'bob@localhost')

    view_path = return_event.value[0]
    props = return_event.value[1]
    view4 = bus.get_object(conn.bus_name, view_path)

    assert props['org.laptop.Telepathy.Channel.Type.ActivityView.Properties'] == \
            dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
    assert conn.InspectHandles(1, props['org.laptop.Telepathy.Channel.Type.ActivityView.Participants']) == \
            ["alice@localhost", "bob@localhost"]
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)

    buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')
    requests_iface = dbus.Interface(conn, tp_name_prefix + '.Connection.Interface.Requests')

    # Gadget was not announced yet
    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.BuddyView',
            'org.laptop.Telepathy.Channel.Interface.View.MaxSize': 5,
          })

    event = q.expect('dbus-error', method='CreateChannel')
    announce_gadget(q, stream, disco_event.stanza)
    call_async(q, conn, 'RequestHandles', 1, ['bob@localhost'])

    event = q.expect('dbus-return', method='RequestHandles')
    handles = event.value[0]
    bob_handle = handles[0]

    call_async(q, buddy_info_iface, 'GetProperties', bob_handle)

    # wait for pubsub query
    event = q.expect('stream-iq', to='bob@localhost', query_ns=ns.PUBSUB)
    query = event.stanza
    assert query['to'] == 'bob@localhost'

    # send an error as reply
    reply = IQ(stream, 'error')
    reply['id'] = query['id']
    reply['to'] = 'alice@localhost'
    reply['from'] = 'bob@localhost'
    stream.send(reply)

    # wait for buddy search query
    event = q.expect('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_BUDDY)
    buddies = xpath.queryForNodes('/iq/query/buddy', event.stanza)
    assert len(buddies) == 1
    buddy = buddies[0]
    assert buddy['jid'] == 'bob@localhost'

    # send reply to the search query
    reply = make_result_iq(stream, event.stanza)
    reply['from'] = 'gadget.localhost'
    reply['to'] = 'alice@localhost'
    query = xpath.queryForNodes('/iq/query', reply)[0]
    buddy = query.addElement((None, "buddy"))
    buddy['jid'] = 'bob@localhost'
    properties = buddy.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#005FE4,#00A0FF')}):
        properties.addChild(node)
    stream.send(reply)

    event = q.expect('dbus-return', method='GetProperties')
    props = event.value[0]

    assert props == {'color': '#005FE4,#00A0FF' }

    # check if we can request Buddy views
    properties = conn.GetAll(
        cs.CONN_IFACE_REQUESTS, dbus_interface=dbus.PROPERTIES_IFACE)

    assert ({tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView'},
            [olpc_name_prefix + '.Channel.Interface.View.MaxSize',
             olpc_name_prefix + '.Channel.Type.BuddyView.Properties',
             olpc_name_prefix + '.Channel.Type.BuddyView.Alias'],
         ) in properties.get('RequestableChannelClasses'),\
                 properties['RequestableChannelClasses']

    # request 3 random buddies
    call_async(q, requests_iface, 'CreateChannel',
        { tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView',
          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 3
          })

    iq_event, return_event, new_channels_event, new_channel_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_BUDDY),
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        EventPattern('dbus-signal', signal='NewChannel'))

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '1'
    assert view['size'] == '3'

    # reply to random query
    reply = make_result_iq(stream, iq_event.stanza)
    reply['from'] = 'gadget.localhost'
    reply['to'] = 'alice@localhost'
    view = xpath.queryForNodes('/iq/view', reply)[0]
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'charles@localhost'
    properties = buddy.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#AAAAAA,#BBBBBB')}):
        properties.addChild(node)
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'bob@localhost'
    properties = buddy.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#005FE4,#00A0FF')}):
        properties.addChild(node)
    stream.send(reply)

    view_path = return_event.value[0]
    props = return_event.value[1]
    view1 = bus.get_object(conn.bus_name, view_path)

    # check NewChannels arg
    channels = new_channels_event.args[0]
    assert len(channels) == 1
    chan, props_ = channels[0]
    assert chan == view_path
    assert props == props_

    # check NewChannel arg
    chan = new_channel_event.args[0]
    assert chan == view_path

    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Properties'] == {}
    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Alias'] == ''

    # check org.freedesktop.Telepathy.Channel D-Bus properties
    props = view1.GetAll(cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['ChannelType'] == 'org.laptop.Telepathy.Channel.Type.BuddyView'
    assert 'org.laptop.Telepathy.Channel.Interface.View' in props['Interfaces']
    assert props['TargetHandle'] == 0
    assert props['TargetID'] == ''
    assert props['TargetHandleType'] == 0

    # check org.laptop.Telepathy.Channel.Interface.View D-Bus properties
    props = view1.GetAll(
        'org.laptop.Telepathy.Channel.Interface.View',
        dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['MaxSize'] == 3

    # check org.laptop.Telepathy.Channel.Type.BuddyView D-Bus properties
    props = view1.GetAll(
        'org.laptop.Telepathy.Channel.Type.BuddyView',
        dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['Properties'] == {}
    assert props['Alias'] == ''

    assert view1.GetChannelType(dbus_interface=cs.CHANNEL) ==\
            'org.laptop.Telepathy.Channel.Type.BuddyView'

    event = q.expect('dbus-signal', signal='BuddiesChanged')
    added, removed = event.args
    assert removed == []
    assert len(added) == 2
    assert sorted(conn.InspectHandles(1, added)) == ['bob@localhost',
            'charles@localhost']

    event = q.expect('dbus-signal', signal='PropertiesChanged')
    event = q.expect('dbus-signal', signal='PropertiesChanged')

    # we can now get bob's properties
    bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0]
    props = buddy_info_iface.GetProperties(bob_handle)
    assert props == {'color': '#005FE4,#00A0FF'}

    # Bob changed his properties
    message = create_gadget_message("test@localhost")

    change = message.addElement((ns.OLPC_BUDDY, 'change'))
    change['jid'] = 'bob@localhost'
    change['id'] = '1'
    properties = change.addElement((ns.OLPC_BUDDY_PROPS, 'properties'))
    for node in properties_to_xml({'color': ('str', '#FFFFFF,#AAAAAA')}):
        properties.addChild(node)

    stream.send(message)

    event = q.expect('dbus-signal', signal='PropertiesChanged',
            args=[bob_handle, {'color': '#FFFFFF,#AAAAAA'}])

    # we now get the new properties
    props = buddy_info_iface.GetProperties(bob_handle)
    assert props == {'color': '#FFFFFF,#AAAAAA'}

    # buddy search
    props = dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
    call_async(q, requests_iface, 'CreateChannel',
        { tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView',
          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 10,
          olpc_name_prefix + '.Channel.Type.BuddyView.Properties': props
          })

    iq_event, return_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost', query_ns=ns.OLPC_BUDDY),
        EventPattern('dbus-return', method='CreateChannel'))

    properties_node = xpath.queryForNodes('/iq/view/buddy/properties',
            iq_event.stanza)
    props = parse_properties(properties_node[0])
    assert props == {'color': ('str', '#AABBCC,#001122')}

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '2'
    assert view['size'] == '10'

    # reply to request
    reply = make_result_iq(stream, iq_event.stanza)
    reply['from'] = 'gadget.localhost'
    reply['to'] = 'alice@localhost'
    view = xpath.queryForNodes('/iq/view', reply)[0]
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'charles@localhost'
    properties = buddy.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#AABBCC,#001122')}):
        properties.addChild(node)
    stream.send(reply)

    view_path = return_event.value[0]
    props = return_event.value[1]
    view2 = bus.get_object(conn.bus_name, view_path)

    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Properties'] == dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Alias'] == ''

    # check org.laptop.Telepathy.Channel.Type.BuddyView D-Bus properties
    props = view2.GetAll(
        'org.laptop.Telepathy.Channel.Type.BuddyView',
        dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['Properties'] == {'color': '#AABBCC,#001122'}
    assert props['Alias'] == ''

    event = q.expect('dbus-signal', signal='BuddiesChanged')
    added, removed = event.args
    assert removed == []
    assert len(added) == 1
    handle = added[0]
    assert conn.InspectHandles(1, [handle])[0] == 'charles@localhost'

    event = q.expect('dbus-signal', signal='PropertiesChanged')
    handle, props = event.args
    assert conn.InspectHandles(1, [handle])[0] == 'charles@localhost'
    assert props == {'color': '#AABBCC,#001122'}

    # add a buddy to view 1
    message = create_gadget_message("test@localhost")

    added = message.addElement((ns.OLPC_BUDDY, 'added'))
    added['id'] = '1'
    buddy = added.addElement((None, 'buddy'))
    buddy['jid'] = 'oscar@localhost'
    properties = buddy.addElement((ns.OLPC_BUDDY_PROPS, "properties"))
    for node in properties_to_xml({'color': ('str', '#000000,#AAAAAA')}):
        properties.addChild(node)

    stream.send(message)

    event = q.expect('dbus-signal', signal='BuddiesChanged')
    added, removed = event.args
    assert removed == []
    assert len(added) == 1
    handle = added[0]
    assert conn.InspectHandles(1, added)[0] == 'oscar@localhost'

    members = view1.Get(olpc_name_prefix + '.Channel.Interface.View',
        'Buddies', dbus_interface=dbus.PROPERTIES_IFACE)

    members = sorted(conn.InspectHandles(1, members))
    assert sorted(members) == ['bob@localhost', 'charles@localhost',
            'oscar@localhost']

    # remove a buddy from view 1
    message = create_gadget_message("test@localhost")

    added = message.addElement((ns.OLPC_BUDDY, 'removed'))
    added['id'] = '1'
    buddy = added.addElement((None, 'buddy'))
    buddy['jid'] = 'bob@localhost'

    stream.send(message)

    event = q.expect('dbus-signal', signal='BuddiesChanged')
    added, removed = event.args
    assert added == []
    assert len(removed) == 1
    handle = removed[0]
    assert conn.InspectHandles(1, [handle])[0] == 'bob@localhost'

    members = view1.Get(olpc_name_prefix + '.Channel.Interface.View',
        'Buddies', dbus_interface=dbus.PROPERTIES_IFACE)
    members = sorted(conn.InspectHandles(1, members))
    assert sorted(members) == ['charles@localhost', 'oscar@localhost']

    # test alias search
    call_async(q, requests_iface, 'CreateChannel',
        { tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView',
          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 10,
          olpc_name_prefix + '.Channel.Type.BuddyView.Alias': 'tom'
          })


    iq_event, return_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_BUDDY),
        EventPattern('dbus-return', method='CreateChannel'))

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '3'
    assert view['size'] == '10'
    buddy = xpath.queryForNodes('/iq/view/buddy', iq_event.stanza)
    assert len(buddy) == 1
    assert buddy[0]['alias'] == 'tom'

    # reply to random query
    reply = make_result_iq(stream, iq_event.stanza)
    reply['from'] = 'gadget.localhost'
    reply['to'] = 'alice@localhost'
    view = xpath.queryForNodes('/iq/view', reply)[0]
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'tom@localhost'
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'thomas@localhost'
    stream.send(reply)

    view_path = return_event.value[0]
    props = return_event.value[1]
    view3 = bus.get_object(conn.bus_name, view_path)

    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Properties'] == {}
    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Alias'] == 'tom'

    # check org.laptop.Telepathy.Channel.Type.BuddyView D-Bus properties
    props = view3.GetAll(
        'org.laptop.Telepathy.Channel.Type.BuddyView',
        dbus_interface=dbus.PROPERTIES_IFACE)

    assert props['Properties'] == {}
    assert props['Alias'] == 'tom'

    event = q.expect('dbus-signal', signal='BuddiesChanged')
    added, removed = event.args
    assert removed == []
    assert len(added) == 2
    assert sorted(conn.InspectHandles(1, added)) == ['thomas@localhost',
            'tom@localhost']

    close_view(q, view1, '1')

    close_view(q, view2, '2')

    close_view(q, view3, '3')

    # View request without MaxSize property
    call_async(q, requests_iface, 'CreateChannel',
        { cs.CHANNEL_TYPE:
            'org.laptop.Telepathy.Channel.Type.BuddyView',
          })

    event = q.expect('dbus-error', method='CreateChannel')
    assert event.error.get_dbus_name() == cs.INVALID_ARGUMENT

    # test alias and properties search
    props = dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
    call_async(q, requests_iface, 'CreateChannel',
        { tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView',
          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 5,
          olpc_name_prefix + '.Channel.Type.BuddyView.Properties': props,
          olpc_name_prefix + '.Channel.Type.BuddyView.Alias': 'jean'
          })

    iq_event, return_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost', query_ns=ns.OLPC_BUDDY),
        EventPattern('dbus-return', method='CreateChannel'))

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '4'
    assert view['size'] == '5'

    properties_node = xpath.queryForNodes('/iq/view/buddy/properties',
            iq_event.stanza)
    props = parse_properties(properties_node[0])
    assert props == {'color': ('str', '#AABBCC,#001122')}

    buddy = xpath.queryForNodes('/iq/view/buddy', iq_event.stanza)
    assert len(buddy) == 1
    assert buddy[0]['alias'] == 'jean'

    view_path = return_event.value[0]
    props = return_event.value[1]
    view4 = bus.get_object(conn.bus_name, view_path)

    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Properties'] == dbus.Dictionary({'color': '#AABBCC,#001122'}, signature='sv')
    assert props['org.laptop.Telepathy.Channel.Type.BuddyView.Alias'] == 'jean'
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)
    announce_gadget(q, stream, disco_event.stanza)

    buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')

    handles = {}

    # Alice is one of our friend so we receive her PEP notifications
    handles['alice'] = conn.RequestHandles(1, ['alice@localhost'])[0]

    # 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'])

    # request a activity view containing only Bob and one
    # activity in it.
    request_random_activity_view(q, stream, conn, 1, '1',
        [('activity3', '*****@*****.**', {},
            [('bob@localhost', {}),]),])

    # Gadget sends us a current-activity change concerning a
    # known activity
    send_gadget_current_activity_changed_msg(stream, 'bob@localhost', '1',
        'activity3', '*****@*****.**')

    # Gadget notifies us about the change
    event = q.expect('dbus-signal', signal='CurrentActivityChanged')
    handles['bob'], id, handles['room3'] = event.args
    assert id == 'activity3'
    assert conn.InspectHandles(1, [handles['bob']]) == \
            ['bob@localhost']
    assert conn.InspectHandles(2, [handles['room3']]) == \
            ['*****@*****.**']

    # And the cache was properly updated
    assert buddy_info_iface.GetCurrentActivity(handles['bob']) == \
            ('activity3', handles['room3'])

    # Gadget sends us a current-activity change concerning an
    # unknown activity
    send_gadget_current_activity_changed_msg(stream, 'bob@localhost', '1',
        'activity4', '*****@*****.**')

    # Gadget changed Alice's current-activity to none as it doesn't
    # know the activity
    event = q.expect('dbus-signal', signal='CurrentActivityChanged',
            args=[handles['bob'], '', 0])

    call_async(q, buddy_info_iface, "GetCurrentActivity", handles['bob'])

    # Bob's current-activity is not in the cache anymore so Gabble try
    # to send a PEP query
    event = q.expect('stream-iq', iq_type='get', query_name='pubsub')
    iq = event.stanza

    # Alice is not Bob's friend so she can't query his PEP node
    answer_error_to_pubsub_request(stream, iq)

    # so Bob is considererd without current activity
    q.expect('dbus-return', method='GetCurrentActivity',
            value=('', 0))
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)

    buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo')
    gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget')
    requests_iface = dbus.Interface(conn, tp_name_prefix + '.Connection.Interface.Requests')
    simple_presence_iface = dbus.Interface(conn, tp_name_prefix + '.Connection.Interface.SimplePresence')

    announce_gadget(q, stream, disco_event.stanza)
    sync_stream(q, stream)

    # receive presence from Charles
    send_presence(stream, 'charles@localhost/Telepathy', 'dnd', 'Hacking on Sugar')

    event, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged'),
        EventPattern('dbus-signal', signal='PresenceUpdate'))

    # get contacts handles
    contacts = ['bob', 'charles', 'damien', 'eric', 'fred']
    tmp = conn.RequestHandles(1, map(lambda x: "%s@localhost" % x, contacts))
    handles = dict(zip(contacts, tmp))

    presence = event.args[0]
    # Connection_Presence_Type_Busy = 6
    assert presence[handles['charles']] == (6, 'dnd', 'Hacking on Sugar')

    # request 3 random buddies
    call_async(q, requests_iface, 'CreateChannel',
        { tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView',
          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 3
          })

    iq_event, return_event, new_channels_event, new_channel_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_BUDDY),
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        EventPattern('dbus-signal', signal='NewChannel'))

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '1'
    assert view['size'] == '3'

    # reply to random query
    reply = make_result_iq(stream, iq_event.stanza)
    reply['from'] = 'gadget.localhost'
    reply['to'] = 'alice@localhost'
    view = xpath.queryForNodes('/iq/view', reply)[0]
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'charles@localhost'
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'bob@localhost'
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'damien@localhost'
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'eric@localhost'
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'fred@localhost'
    stream.send(reply)

    view_path = return_event.value[0]
    props = return_event.value[1]
    view1 = bus.get_object(conn.bus_name, view_path)

    event, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged'),
        EventPattern('dbus-signal', signal='PresenceUpdate'))

    # Only Bob and Damien presences are changed as we received a presence from Charles
    presence = event.args[0]
    assert len(presence) == 4
    # Connection_Presence_Type_Available = 2
    assert presence[handles['bob']] == (2, 'available', '')
    assert presence[handles['damien']] == (2, 'available', '')
    assert presence[handles['eric']] == (2, 'available', '')
    assert presence[handles['fred']] == (2, 'available', '')

    # Charles's presence didn't change
    presence = simple_presence_iface.GetPresences([handles['charles']])
    assert presence[handles['charles']] == (6, 'dnd', 'Hacking on Sugar')

    event = q.expect('dbus-signal', signal='BuddiesChanged')

    # remove bob from view
    remove_buddy_from_view(stream, '1', 'bob@localhost')
    event = q.expect('dbus-signal', signal='BuddiesChanged')

    event, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged'),
        EventPattern('dbus-signal', signal='PresenceUpdate'))

    presence = event.args[0]
    # Connection_Presence_Type_Unknown = 7
    assert presence[handles['bob']] == (7, 'unknown', '')

    # remove charles from view
    remove_buddy_from_view(stream, '1', 'charles@localhost')
    event = q.expect('dbus-signal', signal='BuddiesChanged')

    # Charles's presence didn't change
    presence = simple_presence_iface.GetPresences([handles['charles']])
    assert presence[handles['charles']] == (6, 'dnd', 'Hacking on Sugar')

    # we receive a presence from Dambien
    send_presence(stream, 'damien@localhost/Telepathy', 'away', 'Watching pr0n')

    # presence is properly changed
    event, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged'),
        EventPattern('dbus-signal', signal='PresenceUpdate'))

    presence = event.args[0]
    # Connection_Presence_Type_Away = 3
    assert presence[handles['damien']] == (3, 'away', 'Watching pr0n')

    # remove Damien from view
    remove_buddy_from_view(stream, '1', 'damien@localhost')
    event = q.expect('dbus-signal', signal='BuddiesChanged')

    # Damien's presence didn't change
    presence = simple_presence_iface.GetPresences([handles['damien']])
    assert presence[handles['damien']] == (3, 'away', 'Watching pr0n')

    # request a second view
    call_async(q, requests_iface, 'CreateChannel',
        { tp_name_prefix + '.Channel.ChannelType':
            olpc_name_prefix + '.Channel.Type.BuddyView',
          olpc_name_prefix + '.Channel.Interface.View.MaxSize': 1
          })

    iq_event, return_event, new_channels_event, new_channel_event = q.expect_many(
        EventPattern('stream-iq', to='gadget.localhost',
            query_ns=ns.OLPC_BUDDY),
        EventPattern('dbus-return', method='CreateChannel'),
        EventPattern('dbus-signal', signal='NewChannels'),
        EventPattern('dbus-signal', signal='NewChannel'))

    view = iq_event.stanza.firstChildElement()
    assert view.name == 'view'
    assert view['id'] == '2'
    assert view['size'] == '1'

    # reply to random query
    reply = make_result_iq(stream, iq_event.stanza)
    reply['from'] = 'gadget.localhost'
    reply['to'] = 'alice@localhost'
    view = xpath.queryForNodes('/iq/view', reply)[0]
    buddy = view.addElement((None, "buddy"))
    buddy['jid'] = 'fred@localhost'
    stream.send(reply)

    view_path = return_event.value[0]
    props = return_event.value[1]
    view2 = bus.get_object(conn.bus_name, view_path)

    event = q.expect('dbus-signal', signal='BuddiesChanged')

    # Fred is the only buddy in this view
    buddies = view2.Get('org.laptop.Telepathy.Channel.Interface.View', 'Buddies',
        dbus_interface=dbus.PROPERTIES_IFACE)
    assert buddies == [handles['fred']]

    # ... and his presence didn't change
    presence = simple_presence_iface.GetPresences([handles['fred']])
    assert presence[handles['fred']] == (2, 'available', '')

    # close view 1
    view1.Close(dbus_interface=cs.CHANNEL)

    # Eric's presence is changed as he's not in the view anymore
    event, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged'),
        EventPattern('dbus-signal', signal='PresenceUpdate'))

    presence = event.args[0]
    # Connection_Presence_Type_Unknown = 7
    assert presence[handles['eric']] == (7, 'unknown', '')

    # but not the presence of Fred as he's still in view2
    presence = simple_presence_iface.GetPresences([handles['fred']])
    assert presence[handles['fred']] == (2, 'available', '')

    # close view 2
    view2.Close(dbus_interface=cs.CHANNEL)

   # and now Fred is offline
    event, _ = q.expect_many(
        EventPattern('dbus-signal', signal='PresencesChanged'),
        EventPattern('dbus-signal', signal='PresenceUpdate'))

    presence = event.args[0]
    # Connection_Presence_Type_Unknown = 7
    assert presence[handles['fred']] == (7, 'unknown', '')