コード例 #1
0
def test_ensure(q, bus, account, conn, chan, expected_handler_path):
    """Tests that a client Ensure-ing the channel causes HandleChannels to be
    called on the current handler. (Previously, DelegateChannels() and
    PresentChannel() both broke this.)"""
    cd = ChannelDispatcher(bus)
    call_async(q, cd, 'EnsureChannel', account.object_path, REQUEST, 0, '')
    e = q.expect('dbus-return', method='EnsureChannel')

    cr = ChannelRequest(bus, e.value[0])
    cr.Proceed()

    e = q.expect('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS,
        method='EnsureChannel',
        path=conn.object_path, args=[REQUEST], handled=False)
    q.dbus_return(e.message, False,
        chan.object_path, chan.immutable, signature='boa{sv}')

    e = q.expect('dbus-method-call',
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)
    assertEquals(expected_handler_path, e.path)
    q.dbus_return(e.message, signature='')
コード例 #2
0
def test(q, bus, mc):
    params = dbus.Dictionary(
        {
            "account": "*****@*****.**",
            "password": "******"
        },
        signature='sv')
    simulated_cm, account = create_fakecm_account(q, bus, mc, params)
    conn = enable_fakecm_account(q, bus, mc, account, params)

    text_fixed_properties = dbus.Dictionary(
        {
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        },
        signature='sv')

    client = SimulatedClient(q,
                             bus,
                             'Empathy',
                             observe=[text_fixed_properties],
                             approve=[text_fixed_properties],
                             handle=[text_fixed_properties],
                             bypass_approval=False)

    # No Approver should be invoked at any point during this test, because the
    # Channel was Requested
    def fail_on_approval(e):
        raise AssertionError('Approver should not be invoked')

    q.add_dbus_method_impl(fail_on_approval,
                           path=client.object_path,
                           interface=cs.APPROVER,
                           method='AddDispatchOperation')

    # wait for MC to download the properties
    expect_client_setup(q, [client])

    user_action_time = dbus.Int64(1238582606)

    # chat UI calls ChannelDispatcher.CreateChannel
    cd = ChannelDispatcher(bus)
    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    request_path = cd.CreateChannel(account.object_path, request,
                                    user_action_time, client.bus_name)

    add_request = q.expect('dbus-method-call',
                           handled=False,
                           interface=cs.CLIENT_IFACE_REQUESTS,
                           method='AddRequest',
                           path=client.object_path)
    assert add_request.args[0] == request_path
    q.dbus_return(add_request.message, signature='')

    cr = bus.get_object(cs.CD, request_path)
    request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE)
    assert request_props['Account'] == account.object_path
    assert request_props['Requests'] == [request]
    assert request_props['UserActionTime'] == user_action_time

    # chat UI connects to signals and calls ChannelRequest.Proceed()
    cr.Proceed()
    cm_request_call = q.expect('dbus-method-call',
                               interface=cs.CONN_IFACE_REQUESTS,
                               method='CreateChannel',
                               path=conn.object_path,
                               args=[request],
                               handled=False)

    # Actually, never mind.
    cr.Cancel()

    # Time passes. A channel is returned.
    channel_immutable = dbus.Dictionary(request)
    channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident
    channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle
    channel_immutable[cs.CHANNEL + '.Requested'] = True
    channel_immutable[cs.CHANNEL + '.Interfaces'] = \
        dbus.Array([], signature='s')
    channel_immutable[cs.CHANNEL + '.TargetHandle'] = \
        conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    channel = SimulatedChannel(conn, channel_immutable)

    # this order of events is guaranteed by telepathy-spec (since 0.17.14)
    q.dbus_return(cm_request_call.message,
                  channel.object_path,
                  channel.immutable,
                  signature='oa{sv}')
    channel.announce()

    # Channel is unwanted now, MC stabs it in the face
    stdsig, _ = q.expect_many(
        EventPattern('dbus-signal',
                     path=request_path,
                     interface=cs.CR,
                     signal='Failed'),
        EventPattern('dbus-method-call',
                     path=channel.object_path,
                     interface=cs.CHANNEL,
                     method='Close',
                     handled=True),
    )
コード例 #3
0
def test_channel_creation(q, bus, account, client, conn, ensure):
    user_action_time = dbus.Int64(1238582606)

    # chat UI calls ChannelDispatcher.EnsureChannel or CreateChannel
    cd = ChannelDispatcher(bus)
    request = dbus.Dictionary({
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
            }, signature='sv')

    if ensure:
        method = cd.EnsureChannel
    else:
        method = cd.CreateChannel

    request_path = method(account.object_path, request,
        user_action_time, client.bus_name)

    cr = bus.get_object(cs.CD, request_path)
    request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE)
    assert request_props['Account'] == account.object_path
    assert request_props['Requests'] == [request]
    assert request_props['UserActionTime'] == user_action_time

    add_request = q.expect('dbus-method-call', handled=False,
        interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest',
        path=client.object_path)

    assert add_request.args[0] == request_path
    request_props = add_request.args[1]
    assert request_props[cs.CR + '.Account'] == account.object_path
    assert request_props[cs.CR + '.Requests'] == [request]
    assert request_props[cs.CR + '.UserActionTime'] == user_action_time
    assert request_props[cs.CR + '.PreferredHandler'] == client.bus_name

    q.dbus_return(add_request.message, signature='')

    # chat UI connects to signals and calls ChannelRequest.Proceed()
    cr.Proceed()
    cm_request_call = q.expect('dbus-method-call',
                interface=cs.CONN_IFACE_REQUESTS,
                method=(ensure and 'EnsureChannel' or 'CreateChannel'),
                path=conn.object_path, args=[request], handled=False)

    # Time passes. A channel is returned.

    channel_immutable = dbus.Dictionary(request)
    channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident
    channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle
    channel_immutable[cs.CHANNEL + '.Requested'] = True
    channel_immutable[cs.CHANNEL + '.Interfaces'] = \
        dbus.Array([], signature='s')
    channel_immutable[cs.CHANNEL + '.TargetHandle'] = \
        conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    channel = SimulatedChannel(conn, channel_immutable)

    # this order of events is guaranteed by telepathy-spec (since 0.17.14)
    if ensure:
        q.dbus_return(cm_request_call.message, True, # <- Yours
                channel.object_path, channel.immutable, signature='boa{sv}')
    else:   # Create
        q.dbus_return(cm_request_call.message,
                channel.object_path, channel.immutable, signature='oa{sv}')
    channel.announce()

    # Observer should get told, processing waits for it
    e = q.expect('dbus-method-call',
            path=client.object_path,
            interface=cs.OBSERVER, method='ObserveChannels',
            handled=False)
    assert e.args[0] == account.object_path, e.args
    assert e.args[1] == conn.object_path, e.args
    assert e.args[3] == '/', e.args         # no dispatch operation
    assert e.args[4] == [request_path], e.args
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == channel.object_path, channels
    assert channels[0][1] == channel_immutable, channels

    # Observer says "OK, go"
    q.dbus_return(e.message, signature='')

    # Handler is next
    e = q.expect('dbus-method-call',
            path=client.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)
    assert e.args[0] == account.object_path, e.args
    assert e.args[1] == conn.object_path, e.args
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == channel.object_path, channels
    assert channels[0][1] == channel_immutable, channels
    assert e.args[3] == [request_path], e.args

    # Handler accepts the Channels
    q.dbus_return(e.message, signature='')

    # CR emits Succeeded
    q.expect('dbus-signal', path=request_path,
                interface=cs.CR, signal='Succeeded')

    # Close the channel
    channel.close()
コード例 #4
0
def test_channel_creation(q,
                          bus,
                          account,
                          client,
                          conn,
                          ensure=False,
                          prefer=None,
                          channel_type=cs.CHANNEL_TYPE_TEXT):
    user_action_time = dbus.Int64(1238582606)
    hints = dbus.Dictionary({'badger': 42, 'snake': 'pony'}, signature='sv')

    if prefer is None:
        prefer = client

    cd = ChannelDispatcher(bus)
    assert cd.Properties.Get(cs.CD, "SupportsRequestHints")

    # chat UI calls ChannelDispatcher.EnsureChannelWithHints or
    # CreateChannelWithHints
    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': channel_type,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    call_async(
        q,
        cd, (ensure and 'EnsureChannelWithHints' or 'CreateChannelWithHints'),
        account.object_path,
        request,
        user_action_time,
        prefer.bus_name,
        hints,
        dbus_interface=cs.CD)
    ret = q.expect('dbus-return',
                   method=(ensure and 'EnsureChannelWithHints'
                           or 'CreateChannelWithHints'))
    request_path = ret.value[0]

    # chat UI connects to signals and calls ChannelRequest.Proceed()

    cr = bus.get_object(cs.AM, request_path)
    request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE)
    assert request_props['Account'] == account.object_path
    assert request_props['Requests'] == [request]
    assert request_props['UserActionTime'] == user_action_time
    assert request_props['PreferredHandler'] == prefer.bus_name
    assert request_props['Interfaces'] == []
    assertEquals(hints, request_props['Hints'])

    cr.Proceed(dbus_interface=cs.CR)

    # FIXME: should the EnsureChannel/CreateChannel call, and the AddRequest
    # call, be in a defined order? Probably not though, since CMs and Clients
    # aren't meant to be the same process!

    cm_request_call, add_request_call = q.expect_many(
        EventPattern('dbus-method-call',
                     interface=cs.CONN_IFACE_REQUESTS,
                     method=(ensure and 'EnsureChannel' or 'CreateChannel'),
                     path=conn.object_path,
                     args=[request],
                     handled=False),
        EventPattern('dbus-method-call',
                     handled=False,
                     interface=cs.CLIENT_IFACE_REQUESTS,
                     method='AddRequest'),
    )

    assert add_request_call.args[0] == request_path
    assert add_request_call.path == prefer.object_path
    request_props = add_request_call.args[1]
    assert request_props[cs.CR + '.Account'] == account.object_path
    assert request_props[cs.CR + '.Requests'] == [request]
    assert request_props[cs.CR + '.UserActionTime'] == user_action_time
    assert request_props[cs.CR + '.PreferredHandler'] == prefer.bus_name
    assert request_props[cs.CR + '.Interfaces'] == []

    q.dbus_return(add_request_call.message, signature='')

    # Time passes. A channel is returned.

    channel_immutable = dbus.Dictionary(request)
    channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident
    channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle
    channel_immutable[cs.CHANNEL + '.Requested'] = True
    channel_immutable[cs.CHANNEL + '.Interfaces'] = \
        dbus.Array([], signature='s')
    channel_immutable[cs.CHANNEL + '.TargetHandle'] = \
        conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    channel = SimulatedChannel(conn, channel_immutable)

    # this order of events is guaranteed by telepathy-spec (since 0.17.14)
    if ensure:
        q.dbus_return(
            cm_request_call.message,
            True,  # <- Yours
            channel.object_path,
            channel.immutable,
            signature='boa{sv}')
    else:  # Create
        q.dbus_return(cm_request_call.message,
                      channel.object_path,
                      channel.immutable,
                      signature='oa{sv}')
    channel.announce()

    if channel_type == cs.CHANNEL_TYPE_TEXT:
        # Observer should get told, processing waits for it
        e = q.expect('dbus-method-call',
                     path=client.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False)
        assert e.args[0] == account.object_path, e.args
        assert e.args[1] == conn.object_path, e.args
        assert e.args[3] == '/', e.args  # no dispatch operation
        assert e.args[4] == [request_path], e.args
        channels = e.args[2]
        assert len(channels) == 1, channels
        assert channels[0][0] == channel.object_path, channels
        assert channels[0][1] == channel_immutable, channels
        info = e.args[5]
        assert info['request-properties'] == {
            request_path: request_props
        }, info

        # Observer says "OK, go"
        q.dbus_return(e.message, signature='')

    # Handler is next
    e = q.expect('dbus-method-call',
                 path=prefer.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)
    assert e.args[0] == account.object_path, e.args
    assert e.args[1] == conn.object_path, e.args
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == channel.object_path, channels
    assert channels[0][1] == channel_immutable, channels
    assert e.args[3] == [request_path], e.args
    assert e.args[4] == user_action_time
    assert isinstance(e.args[5], dict)
    assert len(e.args) == 6

    # Handler accepts the Channels
    q.dbus_return(e.message, signature='')

    # SucceededWithChannel is fired first
    e = q.expect('dbus-signal',
                 path=request_path,
                 interface=cs.CR,
                 signal='SucceededWithChannel')

    assertEquals(conn.object_path, e.args[0])
    assert isinstance(e.args[1], dict), e.args[1]
    assertEquals(channel.object_path, e.args[2])
    assertEquals(channel_immutable, e.args[3])

    # CR emits Succeeded
    q.expect('dbus-signal',
             path=request_path,
             interface=cs.CR,
             signal='Succeeded')

    # Close the channel
    channel.close()
コード例 #5
0
def test_delegate_channel(q, bus, mc, account, conn, chan, empathy, empathy_bus, gs):
    # Test that re-Ensure-ing works before we start Delegating and Presenting.
    test_ensure(q, bus, account, conn, chan, gs.object_path)

    # Now gnome-shell wants to give the channel to another handler
    gs_cd = ChannelDispatcher(bus)
    call_async(q, gs_cd, 'DelegateChannels',
        [chan.object_path], 0, "")

    # Empathy is asked to handle the channel and accept
    e = q.expect('dbus-method-call',
            path=empathy.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_return(e.message, signature='')

    e = q.expect('dbus-return', method='DelegateChannels')
    assertEquals(([chan.object_path], {}), e.value)

    # Test that re-Ensure-ing the channel still works, and sends it to
    # the right place.
    test_ensure(q, bus, account, conn, chan, empathy.object_path)

    # Let's play ping-pong with the channel! Empathy gives the channel
    # back to GS
    emp_cd = ChannelDispatcher(empathy_bus)
    call_async(q, emp_cd, 'DelegateChannels',
        [chan.object_path], 0, "")

    # gnome-shell is asked to handle the channel and accept
    e = q.expect('dbus-method-call',
            path=gs.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_return(e.message, signature='')

    e = q.expect('dbus-return', method='DelegateChannels')
    assertEquals(([chan.object_path], {}), e.value)

    # Test that re-Ensure-ing the channel sttill works, and sends it
    # to the right place.
    test_ensure(q, bus, account, conn, chan, gs.object_path)

    # gnome-shell wants to give it back, again
    call_async(q, gs_cd, 'DelegateChannels',
        [chan.object_path], 0, "")

    # Empathy is asked to handle the channel but refuses
    e = q.expect('dbus-method-call',
            path=empathy.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_raise(e.message, cs.NOT_AVAILABLE, "No thanks")

    # DelegateChannels failed so gnome-shell is still handling the channel
    e = q.expect('dbus-return', method='DelegateChannels')
    assertEquals(([], {chan.object_path: (cs.NOT_AVAILABLE, 'No thanks')}), e.value)

    # Test that re-Ensure-ing the channel sttill works, and sends it
    # to the right place.
    test_ensure(q, bus, account, conn, chan, gs.object_path)

    # Empathy doesn't handle the channel atm but tries to delegates it
    call_async(q, emp_cd, 'DelegateChannels',
        [chan.object_path], 0, "")

    q.expect('dbus-error', method='DelegateChannels', name=cs.NOT_YOURS)

    # gnome-shell which is handling the channel asks to re-ensure it
    call_async(q, gs_cd, 'PresentChannel',
        chan.object_path, 0)

    # gnome-shell is asked to re-handle the channel
    e = q.expect('dbus-method-call',
            path=gs.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_return(e.message, signature='')

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

    # empathy which is not handling the channel asks to re-ensure it
    call_async(q, emp_cd, 'PresentChannel',
        chan.object_path, 0)

    # gnome-shell is asked to re-handle the channel
    e = q.expect('dbus-method-call',
            path=gs.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_return(e.message, signature='')

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

    # Test that re-Ensure-ing the channel *still* works, and sends it
    # to the right place.
    test_ensure(q, bus, account, conn, chan, gs.object_path)

    # Empathy crashes
    empathy.release_name()

    e = q.expect('dbus-signal',
            signal='NameOwnerChanged',
            predicate=(lambda e:
                e.args[0] == empathy.bus_name and e.args[2] == ''),
            )

    # gnome-shell wants to delegate, but there is no other handler
    call_async(q, gs_cd, 'DelegateChannels',
        [chan.object_path], 0, "")

    e = q.expect('dbus-return', method='DelegateChannels')
    delegated, not_delegated = e.value
    assertEquals([], delegated)
    error = not_delegated[chan.object_path]
    assertEquals (error[0], cs.NOT_CAPABLE)

    chan.close()
コード例 #6
0
def test(q, bus, mc):
    params = dbus.Dictionary({"account": "*****@*****.**",
        "password": "******"}, signature='sv')
    simulated_cm, account = create_fakecm_account(q, bus, mc, params)
    conn = enable_fakecm_account(q, bus, mc, account, params)

    text_fixed_properties = dbus.Dictionary({
        cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
        cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
        }, signature='sv')

    # Empathy Chat is a text handler
    empathy_bus = dbus.bus.BusConnection()
    empathy = SimulatedClient(q, empathy_bus, 'EmpathyChat',
            handle=[text_fixed_properties], bypass_approval=False)
    q.attach_to_bus(empathy_bus)

    # gnome-shell is a text approver and handler
    gs = SimulatedClient(q, bus, 'GnomeShell',
           approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)

    # wait for MC to download the properties
    expect_client_setup(q, [empathy, gs])

    cd = ChannelDispatcher(bus)

    # incoming text channel
    channel_properties = dbus.Dictionary(text_fixed_properties,
            signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet'
    channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet'
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

    chan = SimulatedChannel(conn, channel_properties)
    chan.announce()

    # gnome-shell's approver is notified
    e = q.expect('dbus-method-call', path=gs.object_path,
        interface=cs.APPROVER, method='AddDispatchOperation',
        handled=False)

    channels, cdo_path,props = e.args

    cdo = ChannelDispatchOperation(bus, cdo_path)

    q.dbus_return(e.message, signature='')

    # gnome-shell handles the channel itself first
    call_async(q, cdo, 'HandleWith',
            cs.tp_name_prefix + '.Client.GnomeShell')

    e = q.expect('dbus-method-call',
            path=gs.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_return(e.message, signature='')

    # test delegating an incoming channel
    test_delegate_channel(q, bus, mc, account, conn, chan, empathy, empathy_bus, gs)

    # Empathy is back
    empathy = SimulatedClient(q, empathy_bus, 'EmpathyChat',
            handle=[text_fixed_properties], bypass_approval=False)

    expect_client_setup(q, [empathy])

    # gnome-shell requests a channel for itself
    call_async(q, cd, 'CreateChannelWithHints',
            account.object_path, REQUEST, 0,
            cs.tp_name_prefix + '.Client.GnomeShell',
            {})
    e = q.expect('dbus-return', method='CreateChannelWithHints')

    cr = ChannelRequest(bus, e.value[0])
    cr.Proceed()

    e = q.expect('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS,
        method='CreateChannel',
        path=conn.object_path, args=[REQUEST], handled=False)

    # channel is created
    chan = SimulatedChannel(conn, REQUEST)

    q.dbus_return(e.message,
        chan.object_path, chan.immutable, signature='oa{sv}')
    chan.announce()

    # gnome-shell handles the channel
    e = q.expect('dbus-method-call',
            path=gs.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    q.dbus_return(e.message, signature='')

    # test delegating an outgoing channel
    test_delegate_channel(q, bus, mc, account, conn, chan, empathy, empathy_bus, gs)
def test(q, bus, mc):
    params = dbus.Dictionary(
        {
            "account": "*****@*****.**",
            "password": "******"
        },
        signature='sv')
    simulated_cm, account = create_fakecm_account(q, bus, mc, params)
    conn = enable_fakecm_account(q, bus, mc, account, params)

    text_fixed_properties = dbus.Dictionary(
        {
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        },
        signature='sv')

    client = SimulatedClient(q,
                             bus,
                             'Empathy',
                             observe=[text_fixed_properties],
                             approve=[text_fixed_properties],
                             handle=[text_fixed_properties],
                             bypass_approval=False)

    # wait for MC to download the properties
    expect_client_setup(q, [client])

    user_action_time = dbus.Int64(1238582606)

    # chat UI calls ChannelDispatcher.CreateChannel
    cd = ChannelDispatcher(bus)
    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    request_path = cd.CreateChannel(account.object_path, request,
                                    user_action_time, client.bus_name)

    add_request = q.expect('dbus-method-call',
                           handled=False,
                           interface=cs.CLIENT_IFACE_REQUESTS,
                           method='AddRequest',
                           path=client.object_path)
    assert add_request.args[0] == request_path
    q.dbus_return(add_request.message, signature='')

    # chat UI connects to signals and calls ChannelRequest.Proceed()
    cr = bus.get_object(cs.CD, request_path)
    cr.Proceed()
    cm_request_call = q.expect('dbus-method-call',
                               interface=cs.CONN_IFACE_REQUESTS,
                               method='CreateChannel',
                               path=conn.object_path,
                               args=[request],
                               handled=False)

    # Before the channel is returned, we delete the account

    account_iface = dbus.Interface(account, cs.ACCOUNT)
    assert account_iface.Remove() is None
    account_event, account_manager_event = q.expect_many(
        EventPattern('dbus-signal',
                     path=account.object_path,
                     signal='Removed',
                     interface=cs.ACCOUNT,
                     args=[]),
        EventPattern('dbus-signal',
                     path=cs.AM_PATH,
                     signal='AccountRemoved',
                     interface=cs.AM,
                     args=[account.object_path]),
    )

    # You know that request I told you about? Not going to happen.
    remove_request = q.expect('dbus-method-call',
                              interface=cs.CLIENT_IFACE_REQUESTS,
                              method='RemoveRequest',
                              handled=False)
    assert remove_request.args[0] == request_path
    # FIXME: the spec should maybe define what error this will be. Currently,
    # it's Disconnected
    assert remove_request.args[1].startswith(tp_name_prefix + '.Error.')

    q.expect('dbus-signal',
             path=request_path,
             interface=cs.CR,
             signal='Failed',
             args=remove_request.args[1:])

    q.dbus_return(remove_request.message, signature='')

    # ... and the Connection is told to disconnect, hopefully before the
    # Channel has actually been established
    e = q.expect('dbus-method-call',
                 path=conn.object_path,
                 interface=cs.CONN,
                 method='Disconnect',
                 args=[],
                 handled=True)