def run_mixed_test (q, bus, conn, stream):
    conn.Connect()

    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.SquareWheel', [
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
            cs.INITIAL_AUDIO: True},
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA,
            cs.INITIAL_VIDEO: True},
        ], [
            cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/gtalk-p2p',
            cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/ice-udp',
            cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/video/h264',
            ]),
        (cs.CLIENT + '.FlyingCar', [
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
            cs.CALL_INITIAL_AUDIO: True},
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
            cs.CALL_INITIAL_VIDEO: True},
        ], [
            cs.CHANNEL_TYPE_CALL + '/gtalk-p2p',
            cs.CHANNEL_TYPE_CALL + '/ice-udp',
            cs.CHANNEL_TYPE_CALL + '/video/h264',
            ]),
        ])

    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, JINGLE_CAPS)
def advertise_caps(q, conn, stream, filters, expected_features,
                   unexpected_features, expected_caps):
    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    ret_caps = conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.Foo', filters, [])
    ])

    # Expect Gabble to reply with the correct caps
    event, namespaces, _, signaled_caps = receive_presence_and_ask_caps(
        q, stream)

    assertSameElements(expected_caps, signaled_caps)

    assertContains(ns.TUBES, namespaces)

    for var in expected_features:
        assertContains(var, namespaces)

    for var in unexpected_features:
        assertDoesNotContain(var, namespaces)

    # Check our own caps
    caps = get_contacts_capabilities_sync(conn, [self_handle])
    assertSameElements(expected_caps, caps)

    # check the Contacts interface give the same caps
    caps_via_contacts_iface = conn.Contacts.GetContactAttributes(
            [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \
            [self_handle][cs.ATTR_CONTACT_CAPABILITIES]
    assertSameElements(caps[self_handle], caps_via_contacts_iface)
def advertise_caps(q, conn, stream, filters, expected_features, unexpected_features,
                   expected_caps):
    self_handle = conn.GetSelfHandle()
    ret_caps = conn.ContactCapabilities.UpdateCapabilities(
            [(cs.CLIENT + '.Foo', filters, [])])

    # Expect Gabble to reply with the correct caps
    event, namespaces, _, signaled_caps = receive_presence_and_ask_caps(q, stream)

    assertSameElements(expected_caps, signaled_caps)

    assertContains(ns.TUBES, namespaces)

    for var in expected_features:
        assertContains(var, namespaces)

    for var in unexpected_features:
        assertDoesNotContain(var, namespaces)

    # Check our own caps
    caps = conn.ContactCapabilities.GetContactCapabilities([self_handle])
    assertSameElements(expected_caps, caps)

    # check the Contacts interface give the same caps
    caps_via_contacts_iface = conn.Contacts.GetContactAttributes(
            [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \
            [self_handle][cs.ATTR_CONTACT_CAPABILITIES]
    assertSameElements(caps[self_handle], caps_via_contacts_iface)
def advertise_caps(q, bus, conn, stream, filters, expected_features, unexpected_features,
                   expected_caps):
    # make sure nothing from a previous update is still running
    sync_dbus(bus, q, conn)

    self_handle = conn.Properties.Get(cs.CONN, "SelfHandle")
    ret_caps = conn.ContactCapabilities.UpdateCapabilities(
            [(cs.CLIENT + '.Foo', filters, [])])

    # Expect Gabble to reply with the correct caps
    event, namespaces, _, signaled_caps = receive_presence_and_ask_caps(q, stream)

    assertSameElements(expected_caps, signaled_caps[self_handle])

    assertContains(ns.TP_FT_METADATA, namespaces)

    for var in expected_features:
        assertContains(var, namespaces)

    for var in unexpected_features:
        assertDoesNotContain(var, namespaces)

    # Check our own caps
    caps = get_contacts_capabilities_sync(conn, [self_handle])
    assertSameElements(expected_caps, caps[self_handle])

    # check the Contacts interface give the same caps
    caps_via_contacts_iface = conn.Contacts.GetContactAttributes(
            [self_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \
            [self_handle][cs.ATTR_CONTACT_CAPABILITIES]
    assertSameElements(caps[self_handle], caps_via_contacts_iface)
Beispiel #5
0
def test(q, bus, conn, stream):
    q.expect('stream-presence')

    # gabble won't try to represent the client if doesn't have any
    # RCCs or HCTs, so let's add some
    conn.ContactCapabilities.UpdateCapabilities(
        [
            ('dataformtest', [], ['banan', 'hi'])
        ])

    _, _, forms, _ = receive_presence_and_ask_caps(q, stream)

    assertEquals({'gabble:test:channel:manager:data:form':
                      {'cheese': ['omgnothorriblecheese'],
                       'running_out_of': ['ideas', 'cake'],
                       'favourite_crane': ['a tall one', 'a short one'],
                       'animal': ['badger', 'snake', 'weasel']
                       }
                  }, forms)
def test(q, bus, conn, stream):
    q.expect('stream-presence')

    # gabble won't try to represent the client if doesn't have any
    # RCCs or HCTs, so let's add some
    conn.ContactCapabilities.UpdateCapabilities(
        [
            ('dataformtest', [], ['banan', 'hi'])
        ])

    _, _, forms, _ = receive_presence_and_ask_caps(q, stream)

    assertEquals({'gabble:test:channel:manager:data:form':
                      {'cheese': ['omgnothorriblecheese'],
                       'running_out_of': ['ideas', 'cake'],
                       'favourite_crane': ['a tall one', 'a short one'],
                       'animal': ['badger', 'snake', 'weasel']
                       }
                  }, forms)
def run_mixed_test(q, bus, conn, stream):
    conn.Connect()

    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.FlyingCar', [
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
                cs.CALL_INITIAL_AUDIO: True
            },
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL,
                cs.CALL_INITIAL_VIDEO: True
            },
        ], [
            cs.CHANNEL_TYPE_CALL + '/gtalk-p2p',
            cs.CHANNEL_TYPE_CALL + '/ice',
            cs.CHANNEL_TYPE_CALL + '/video/h264',
        ]),
    ])

    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, JINGLE_CAPS)
def run_test(q, bus, conn, stream,
        media_channel_type, media_interface,
        initial_audio, initial_video):
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
            cs.STREAM_TUBE_SERVICE: 'x-abiword' },
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.STREAM_TUBE_SERVICE: 'x-abiword' },
        ], []),
        ])

    conn.Connect()

    _, initial_presence = q.expect_many(
            EventPattern('dbus-signal', signal='StatusChanged',
                args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
            EventPattern('stream-presence'),
            )
    (disco_response, namespaces, _) = disco_caps(q, stream, initial_presence)
    check_caps(namespaces, [ns.TUBES + '/stream#x-abiword'])

    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
            cs.STREAM_TUBE_SERVICE: 'x-abiword' },
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.STREAM_TUBE_SERVICE: 'x-abiword' },
        ], []),
        (cs.CLIENT + '.KCall', [
        { cs.CHANNEL_TYPE: media_channel_type },
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_audio: True},
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_video: True},
        ], [
            media_interface + '/gtalk-p2p',
            media_interface + '/ice-udp',
            media_interface + '/video/h264',
            ]),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, JINGLE_CAPS + [ns.TUBES + '/stream#x-abiword'])

    # Removing our H264 codec removes our ability to do Google Video
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
        { cs.CHANNEL_TYPE: media_channel_type },
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_audio: True},
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_video: True},
        ], [
            media_interface + '/gtalk-p2p',
            media_interface + '/ice-udp',
            ]),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            JINGLE_CAPS_EXCEPT_GVIDEO + [ns.TUBES + '/stream#x-abiword'])

    # Remove AbiWord's caps
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [], []),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, JINGLE_CAPS_EXCEPT_GVIDEO)

    # Remove KCall's caps too
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [], []),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [])

    # If AbiWord claims that it can do MediaSignalling things on its Tubes
    # channels, then it's wrong, and that still doesn't make us callable.
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
            cs.STREAM_TUBE_SERVICE: 'x-abiword' },
        { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
            cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
            cs.STREAM_TUBE_SERVICE: 'x-abiword' },
        ], [
            media_interface + '/gtalk-p2p',
            media_interface + '/ice-udp',
            media_interface + '/video/h264',
            ]),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [ns.TUBES + '/stream#x-abiword'])

    # Remove the broken version of AbiWord's caps
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [], []),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [])

    # Add caps selectively. Here we're callable, but not via ICE-UDP, and not
    # with video.
    #
    # (Jingle and raw UDP need no special client support, so are automatically
    # enabled whenever we can do audio or video.)
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
        { cs.CHANNEL_TYPE: media_channel_type },
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_audio: True},
        ], [media_interface + '/gtalk-p2p']),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            [ns.GOOGLE_P2P, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
                ns.JINGLE_015, ns.GOOGLE_FEAT_VOICE, ns.JINGLE_RTP_AUDIO,
                ns.JINGLE_RTP, ns.JINGLE_015_AUDIO])

    # With AUDIO but no transport, we are only callable via raw UDP, which
    # Google clients cannot do.
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
        { cs.CHANNEL_TYPE: media_channel_type },
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_audio: True},
        ], [])
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            [ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
                ns.JINGLE_015, ns.JINGLE_RTP_AUDIO,
                ns.JINGLE_RTP, ns.JINGLE_015_AUDIO])

    # With VIDEO and ICE-UDP only, we are very futuristic indeed.
    # Google clients cannot interop with us.
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
        { cs.CHANNEL_TYPE: media_channel_type },
        { cs.CHANNEL_TYPE: media_channel_type,
            initial_video: True},
        ], [
            media_interface + '/ice-udp',
            media_interface + '/video/theora',
            ]),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            [ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
                ns.JINGLE_015, ns.JINGLE_RTP_VIDEO,
                ns.JINGLE_RTP, ns.JINGLE_015_VIDEO])

    # Remove KCall to simplify subsequent checks
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [], []),
        ])
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [])

    # Support file transfer
    if FILE_TRANSFER_ENABLED:
        conn.ContactCapabilities.UpdateCapabilities([
            (cs.CLIENT + '.FileReceiver', [{
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_FILE_TRANSFER,
                cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
                }], []),
            ])
        (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
                False)
        check_caps(namespaces, [ns.FILE_TRANSFER])
def run_test(q, bus, conn, stream):
    initial_presence = q.expect('stream-presence')

    # This method call looks wrong, but it's "the other side" of
    # test/twisted/capabilities/legacy-caps.py in MC 5.1 - MC doesn't know
    # how to map Client capabilities into the old Capabilities interface.
    #
    # Also, MC sometimes puts the same channel type in the list twice, so
    # make sure Gabble copes.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, 2L**32-1),
            (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1),
            (cs.CHANNEL_TYPE_STREAM_TUBE, 2L**32-1)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, JINGLE_CAPS)

    # Remove all our caps again
    add = []
    remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA,
            cs.CHANNEL_TYPE_STREAM_TUBE]
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [])

    # Add caps selectively (i.e. what a client that actually understood the
    # old Capabilities interface would do). With AUDIO and GTALK_P2P, we're
    # callable, but not via ICE-UDP, and not with video.
    #
    # (Jingle and raw UDP need no special client support, so are automatically
    # enabled whenever we can do audio or video.)
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA,
        cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_GTALKP2P)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            [ns.GOOGLE_P2P, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
                ns.JINGLE_015, ns.GOOGLE_FEAT_VOICE, ns.JINGLE_RTP_AUDIO,
                ns.JINGLE_RTP, ns.JINGLE_015_AUDIO])

    # Remove all our caps again
    add = []
    remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA,
            cs.CHANNEL_TYPE_STREAM_TUBE]
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [])

    # With AUDIO but no transport, we are only callable via raw UDP, which
    # Google clients cannot do.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_AUDIO)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            [ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
                ns.JINGLE_015, ns.JINGLE_RTP_AUDIO,
                ns.JINGLE_RTP, ns.JINGLE_015_AUDIO])

    # Remove all our caps again
    add = []
    remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA,
            cs.CHANNEL_TYPE_STREAM_TUBE]
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces, [])

    # With VIDEO and ICE-UDP only, we are very futuristic indeed.
    # Google clients cannot interop with us.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA,
        cs.MEDIA_CAP_VIDEO | cs.MEDIA_CAP_ICEUDP)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _, _) = receive_presence_and_ask_caps(q, stream,
            False)
    check_caps(namespaces,
            [ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
                ns.JINGLE_015, ns.JINGLE_RTP_VIDEO,
                ns.JINGLE_RTP, ns.JINGLE_015_VIDEO])
def run_test(q, bus, conn, stream, media_channel_type, media_interface,
             initial_audio, initial_video):
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
                cs.STREAM_TUBE_SERVICE: 'x-abiword'
            },
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
                cs.STREAM_TUBE_SERVICE: 'x-abiword'
            },
        ], []),
    ])

    conn.Connect()

    _, initial_presence = q.expect_many(
        EventPattern('dbus-signal',
                     signal='StatusChanged',
                     args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
        EventPattern('stream-presence'),
    )
    (disco_response, namespaces, _) = disco_caps(q, stream, initial_presence)
    check_caps(namespaces, [ns.TUBES + '/stream#x-abiword'])

    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
                cs.STREAM_TUBE_SERVICE: 'x-abiword'
            },
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
                cs.STREAM_TUBE_SERVICE: 'x-abiword'
            },
        ], []),
        (cs.CLIENT + '.KCall', [
            {
                cs.CHANNEL_TYPE: media_channel_type
            },
            {
                cs.CHANNEL_TYPE: media_channel_type,
                initial_audio: True
            },
            {
                cs.CHANNEL_TYPE: media_channel_type,
                initial_video: True
            },
        ], [
            media_interface + '/gtalk-p2p',
            media_interface + '/ice-udp',
            media_interface + '/video/h264',
        ]),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, JINGLE_CAPS + [ns.TUBES + '/stream#x-abiword'])

    # Removing our H264 codec removes our ability to do Google Video
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
            {
                cs.CHANNEL_TYPE: media_channel_type
            },
            {
                cs.CHANNEL_TYPE: media_channel_type,
                initial_audio: True
            },
            {
                cs.CHANNEL_TYPE: media_channel_type,
                initial_video: True
            },
        ], [
            media_interface + '/gtalk-p2p',
            media_interface + '/ice-udp',
        ]),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces,
               JINGLE_CAPS_EXCEPT_GVIDEO + [ns.TUBES + '/stream#x-abiword'])

    # Remove AbiWord's caps
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [], []),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, JINGLE_CAPS_EXCEPT_GVIDEO)

    # Remove KCall's caps too
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [], []),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [])

    # If AbiWord claims that it can do MediaSignalling things on its Tubes
    # channels, then it's wrong, and that still doesn't make us callable.
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
                cs.STREAM_TUBE_SERVICE: 'x-abiword'
            },
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
                cs.STREAM_TUBE_SERVICE: 'x-abiword'
            },
        ], [
            media_interface + '/gtalk-p2p',
            media_interface + '/ice-udp',
            media_interface + '/video/h264',
        ]),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [ns.TUBES + '/stream#x-abiword'])

    # Remove the broken version of AbiWord's caps
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.AbiWord', [], []),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [])

    # Add caps selectively. Here we're callable, but not via ICE-UDP, and not
    # with video.
    #
    # (Jingle and raw UDP need no special client support, so are automatically
    # enabled whenever we can do audio or video.)
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
            {
                cs.CHANNEL_TYPE: media_channel_type
            },
            {
                cs.CHANNEL_TYPE: media_channel_type,
                initial_audio: True
            },
        ], [media_interface + '/gtalk-p2p']),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [
        ns.GOOGLE_P2P, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015,
        ns.GOOGLE_FEAT_VOICE, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP,
        ns.JINGLE_015_AUDIO
    ])

    # With AUDIO but no transport, we are only callable via raw UDP, which
    # Google clients cannot do.
    conn.ContactCapabilities.UpdateCapabilities([(cs.CLIENT + '.KCall', [
        {
            cs.CHANNEL_TYPE: media_channel_type
        },
        {
            cs.CHANNEL_TYPE: media_channel_type,
            initial_audio: True
        },
    ], [])])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [
        ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015,
        ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP, ns.JINGLE_015_AUDIO
    ])

    # With VIDEO and ICE-UDP only, we are very futuristic indeed.
    # Google clients cannot interop with us.
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [
            {
                cs.CHANNEL_TYPE: media_channel_type
            },
            {
                cs.CHANNEL_TYPE: media_channel_type,
                initial_video: True
            },
        ], [
            media_interface + '/ice-udp',
            media_interface + '/video/theora',
        ]),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [
        ns.JINGLE_TRANSPORT_ICEUDP, ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE,
        ns.JINGLE_015, ns.JINGLE_RTP_VIDEO, ns.JINGLE_RTP, ns.JINGLE_015_VIDEO
    ])

    # Remove KCall to simplify subsequent checks
    conn.ContactCapabilities.UpdateCapabilities([
        (cs.CLIENT + '.KCall', [], []),
    ])
    (disco_response, namespaces, _,
     _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [])

    # Support file transfer
    if FILE_TRANSFER_ENABLED:
        conn.ContactCapabilities.UpdateCapabilities([
            (cs.CLIENT + '.FileReceiver', [{
                cs.CHANNEL_TYPE:
                cs.CHANNEL_TYPE_FILE_TRANSFER,
                cs.TARGET_HANDLE_TYPE:
                cs.HT_CONTACT,
            }], []),
        ])
        (disco_response, namespaces, _,
         _) = receive_presence_and_ask_caps(q, stream, False)
        check_caps(namespaces, [ns.FILE_TRANSFER])
def run_test(q, bus, conn, stream):
    conn.Connect()

    _, initial_presence = q.expect_many(
        EventPattern("dbus-signal", signal="StatusChanged", args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]),
        EventPattern("stream-presence"),
    )

    # This method call looks wrong, but it's "the other side" of
    # test/twisted/capabilities/draft-1.py in MC 5.1 - MC doesn't know
    # how to map Client capabilities into the old Capabilities interface.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, 2L ** 32 - 1), (cs.CHANNEL_TYPE_STREAM_TUBE, 2L ** 32 - 1)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, JINGLE_CAPS)
    # Immediately afterwards, we get SetSelfCapabilities, for which a
    # more comprehensive test exists in tube-caps.py.
    conn.ContactCapabilities.SetSelfCapabilities(
        [
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
                cs.STREAM_TUBE_SERVICE: "x-abiword",
            },
            {
                cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
                cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
                cs.STREAM_TUBE_SERVICE: "x-abiword",
            },
            {cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA},
        ]
    )
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, JINGLE_CAPS + [ns.TUBES + "/stream#x-abiword"])

    # Remove all our caps again
    add = []
    remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_TYPE_STREAM_TUBE]
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [])
    # the call to SSC has no effect here
    conn.ContactCapabilities.SetSelfCapabilities([])
    noop_presence_update(q, stream)

    # Add caps selectively (i.e. what a client that actually understood the
    # old Capabilities interface would do). With AUDIO and GTALK_P2P, we're
    # callable, but not via ICE-UDP, and not with video.
    #
    # (Jingle and raw UDP need no special client support, so are automatically
    # enabled whenever we can do audio or video.)
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_AUDIO | cs.MEDIA_CAP_GTALKP2P)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(
        namespaces,
        [
            ns.GOOGLE_P2P,
            ns.JINGLE_TRANSPORT_RAWUDP,
            ns.JINGLE,
            ns.JINGLE_015,
            ns.GOOGLE_FEAT_VOICE,
            ns.JINGLE_RTP_AUDIO,
            ns.JINGLE_RTP,
            ns.JINGLE_015_AUDIO,
        ],
    )
    # the call to SSC has no effect here
    conn.ContactCapabilities.SetSelfCapabilities([{cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA}])
    noop_presence_update(q, stream)

    # Remove all our caps again
    add = []
    remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_TYPE_STREAM_TUBE]
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [])
    # the call to SSC has no effect here
    conn.ContactCapabilities.SetSelfCapabilities([])
    noop_presence_update(q, stream)

    # With AUDIO but no transport, we are only callable via raw UDP, which
    # Google clients cannot do.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_AUDIO)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(
        namespaces,
        [ns.JINGLE_TRANSPORT_RAWUDP, ns.JINGLE, ns.JINGLE_015, ns.JINGLE_RTP_AUDIO, ns.JINGLE_RTP, ns.JINGLE_015_AUDIO],
    )
    # the call to SSC has no effect here
    conn.ContactCapabilities.SetSelfCapabilities([{cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA}])
    noop_presence_update(q, stream)

    # Remove all our caps again
    add = []
    remove = [cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.CHANNEL_TYPE_STREAM_TUBE]
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(namespaces, [])
    # the call to SSC has no effect here
    conn.ContactCapabilities.SetSelfCapabilities([])
    noop_presence_update(q, stream)

    # With VIDEO and ICE-UDP only, we are very futuristic indeed.
    # Google clients cannot interop with us.
    add = [(cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.MEDIA_CAP_VIDEO | cs.MEDIA_CAP_ICEUDP)]
    remove = []
    caps = conn.Capabilities.AdvertiseCapabilities(add, remove)
    (disco_response, namespaces, _) = receive_presence_and_ask_caps(q, stream, False)
    check_caps(
        namespaces,
        [
            ns.JINGLE_TRANSPORT_ICEUDP,
            ns.JINGLE_TRANSPORT_RAWUDP,
            ns.JINGLE,
            ns.JINGLE_015,
            ns.JINGLE_RTP_VIDEO,
            ns.JINGLE_RTP,
            ns.JINGLE_015_VIDEO,
        ],
    )
    # the call to SSC has no effect here
    conn.ContactCapabilities.SetSelfCapabilities([{cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA}])
    noop_presence_update(q, stream)