コード例 #1
0
def signal_channel_expect_query(q, bus, account, conn, empathy, kopete):
    # This target is special-cased in test-plugin.c
    target = '*****@*****.**'
    channel_properties = dbus.Dictionary(text_fixed_properties,
            signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = target
    channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, target)
    channel_properties[cs.CHANNEL + '.InitiatorID'] = target
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, target)
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = \
            dbus.Array([cs.CHANNEL_IFACE_DESTROYABLE, cs.CHANNEL_IFACE_GROUP,
                ],signature='s')

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

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            )

    # What does the policy service think?
    permission = q.expect('dbus-method-call', path='/com/example/Policy',
            interface='com.example.Policy', method='RequestPermission')

    # Think about it for a bit
    sync_dbus(bus, q, account)

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # Let the test code decide how to reply
    return permission, chan, cdo_path
コード例 #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')

    # Throughout this entire test, we should never be asked to approve or
    # handle a channel.
    forbidden = [
        EventPattern('dbus-method-call', method='AddDispatchOperation'),
        EventPattern('dbus-method-call', method='HandleChannels'),
    ]
    q.forbid_events(forbidden)

    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q,
                              bus,
                              'Empathy',
                              observe=[text_fixed_properties],
                              approve=[text_fixed_properties],
                              handle=[text_fixed_properties],
                              bypass_approval=False)
    kopete = SimulatedClient(q,
                             bus,
                             'Kopete',
                             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, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # This ID is special-cased by the mcp-plugin plugin, which rejects
    # channels to or from it by destroying them, without waiting for observers
    # to return
    target = '*****@*****.**'
    channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = target
    channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, target)
    channel_properties[cs.CHANNEL + '.InitiatorID'] = target
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, target)
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = \
            dbus.Array([cs.CHANNEL_IFACE_DESTROYABLE, cs.CHANNEL_IFACE_GROUP,
                ],signature='s')

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    # The plugin realises we've been rickrolled, and responds. It calls Destroy
    # even though neither Empathy nor Kopete has returned from ObserveChannels
    # yet
    destruction, e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=chan.object_path,
                     interface=cs.CHANNEL_IFACE_DESTROYABLE,
                     method='Destroy',
                     args=[],
                     handled=False),
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
    )
    # treat the destruction like Close
    chan.Close(destruction)

    # Both Observers indicate that they are ready to proceed (somewhat late)
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # When the Observers have returned, the CDO finishes
    q.expect_many(
        EventPattern('dbus-signal',
                     path=cdo_path,
                     interface=cs.CDO,
                     signal='Finished'),
        EventPattern('dbus-signal',
                     path=cs.CD_PATH,
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished',
                     args=[cdo_path]),
    )

    # This ID is also special-cased
    target = '*****@*****.**'
    channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = target
    channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, target)
    channel_properties[cs.CHANNEL + '.InitiatorID'] = target
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, target)
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = \
            dbus.Array([cs.CHANNEL_IFACE_DESTROYABLE, cs.CHANNEL_IFACE_GROUP,
                ],signature='s')

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    # The plugin realises it's MC Hammer, and responds, but its response waits
    # for the observers to return
    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
    )

    sync_dbus(bus, q, account)

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    _, _, e = q.expect_many(
        EventPattern('dbus-signal',
                     path=cdo_path,
                     interface=cs.CDO,
                     signal='Finished'),
        EventPattern('dbus-signal',
                     path=cs.CD_PATH,
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished',
                     args=[cdo_path]),
        EventPattern('dbus-method-call',
                     path=chan.object_path,
                     interface=cs.CHANNEL_IFACE_DESTROYABLE,
                     method='Destroy',
                     handled=False),
    )
    q.dbus_return(e.message, signature='')
    chan.close()
コード例 #3
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)

    abiword_fixed_properties = dbus.Dictionary(
        {
            cs.CHANNEL_TYPE_STREAM_TUBE + '.Service': 'x-abiword',
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAM_TUBE,
        },
        signature='sv')

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    channel_properties = dbus.Dictionary(abiword_fixed_properties,
                                         signature='sv')
    channel_properties[cs.CHANNEL + '.TargetHandleType'] = cs.HT_CONTACT
    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()

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    assert handlers == [cs.tp_name_prefix + '.Client.AbiWord'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    abiword_object_path = cs.tp_path_prefix + '/Client/AbiWord'

    # There are no approvers so the only Handler is asked to handle the
    # channels

    # The fake AbiWord implementation is run
    e = q.expect(
        'dbus-signal',
        path=cs.tp_path_prefix + '/RegressionTests',
        interface=cs.tp_name_prefix + '.RegressionTests',
        signal='FakeStartup',
        args=[cs.tp_name_prefix + '.Client.AbiWord'],
    )
    # We take on its identity to be able to continue with the test
    abiword = SimulatedClient(q,
                              bus,
                              'AbiWord',
                              handle=[abiword_fixed_properties])

    e = q.expect('dbus-method-call',
                 path=abiword.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)
    # AbiWord accepts the channels
    q.dbus_return(e.message, signature='')

    # FIXME: this isn't currently emitted (part of the same bug as emitting
    # it as soon as HandleChannels is called)
    #q.expect('dbus-signal', path=cdo_path, signal='Finished')
    #q.expect('dbus-signal', path=cs.CD_PATH,
    #    signal='DispatchOperationFinished', args=[cdo_path])

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #4
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')
    vague_fixed_properties = dbus.Dictionary({
        cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        }, signature='sv')

    empathy_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    empathy = SimulatedClient(q, empathy_bus, 'Empathy',
            observe=[text_fixed_properties], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)

    # Kopete's filter is less specific than Empathy's, so we'll prefer Empathy
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(kopete_bus)
    kopete = SimulatedClient(q, kopete_bus, 'Kopete',
            observe=[], approve=[],
            handle=[vague_fixed_properties], bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    # In this test Empathy's filter has more things in it than Kopete's, so
    # MC will prefer Empathy
    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    e = q.expect('dbus-method-call',
            path=empathy.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

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

    e = q.expect('dbus-method-call',
            path=empathy.object_path,
            interface=cs.APPROVER, method='AddDispatchOperation',
            handled=False)

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]

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

    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy rejects the channels
    q.dbus_raise(e.message, cs.NOT_AVAILABLE, 'Blind drunk', bus=empathy_bus)

    e = q.expect('dbus-error', method='HandleWith')
    assert e.error.get_dbus_name() == cs.NOT_AVAILABLE
    assert e.error.get_dbus_message() == 'Blind drunk'

    # The channels no longer count as having been approved. Check that MC
    # doesn't carry on regardless
    forbidden = [EventPattern('dbus-method-call', method='HandleChannels')]
    q.forbid_events(forbidden)
    sync_dbus(bus, q, mc)
    q.unforbid_events(forbidden)

    # I'm Feeling Lucky. It might work if I try again? Maybe?
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy rejects the channels, again
    q.dbus_raise(e.message, cs.NOT_CAPABLE, 'Still drunk', bus=empathy_bus)

    e = q.expect('dbus-error', method='HandleWith')
    assert e.error.get_dbus_name() == cs.NOT_CAPABLE
    assert e.error.get_dbus_message() == 'Still drunk'

    # OK, OK, is anyone else competent enough to handle them?
    # (Also, assert that MC doesn't offer them back to Empathy, knowing that
    # it already tried and failed)
    forbidden = [EventPattern('dbus-method-call', method='HandleChannels',
        path=empathy.object_path)]
    q.forbid_events(forbidden)
    call_async(q, cdo_iface, 'HandleWith', '')

    # Kopete is asked to handle the channels
    k = q.expect('dbus-method-call',
                path=kopete.object_path,
                interface=cs.HANDLER, method='HandleChannels',
                handled=False)

    # Kopete rejects the channels too
    q.dbus_raise(k.message, cs.NOT_AVAILABLE, 'Also blind drunk',
            bus=kopete_bus)

    e = q.expect('dbus-error', method='HandleWith')

    assert e.error.get_dbus_name() == cs.NOT_AVAILABLE
    assert e.error.get_dbus_message() == 'Also blind drunk'

    # MC gives up and closes the channel. This is the end of the CDO.
    q.expect_many(
            EventPattern('dbus-method-call', path=chan.object_path,
                interface=cs.CHANNEL, method='Close', args=[]),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #5
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')

    empathy_bus = dbus.bus.BusConnection()
    empathy_bus.set_exit_on_disconnect(False)  # we'll disconnect later
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    q.attach_to_bus(kopete_bus)
    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q,
                              empathy_bus,
                              'Empathy',
                              observe=[text_fixed_properties],
                              approve=[text_fixed_properties],
                              handle=[text_fixed_properties],
                              bypass_approval=False)
    kopete = SimulatedClient(q,
                             kopete_bus,
                             'Kopete',
                             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, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # Using an invalid Handler name should fail
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.The.Moon.On.A.Stick')
    q.expect('dbus-error', method='HandleWith')
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.the moon on a stick')
    q.expect('dbus-error', method='HandleWith')

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWith'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWithTime',
               cs.tp_name_prefix + '.Client.Empathy', 13)

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

    account_path, conn_path, channels, requests, action_time, info = e.args
    assert action_time == 13

    # Empathy accepts the channels
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWithTime'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # From now on, it is an error to get HandleChannels (because we're
    # testing Claim())
    forbidden = [
        EventPattern('dbus-method-call', method='HandleChannels'),
    ]
    q.forbid_events(forbidden)

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

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == claimed_chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=kopete_bus, signature='')
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(claimed_chan.object_path, channel_properties)],
                      cdo_path, cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first, and Empathy decides it wants the
    # channel for itself
    empathy_cdo = empathy_bus.get_object(cdo.bus_name, cdo.object_path)
    empathy_cdo_iface = dbus.Interface(empathy_cdo, cs.CDO)
    call_async(q, empathy_cdo_iface, 'Claim')

    q.expect_many(
        EventPattern('dbus-signal', path=cdo_path, signal='Finished'),
        EventPattern('dbus-signal',
                     path=cs.CD_PATH,
                     signal='DispatchOperationFinished',
                     args=[cdo_path]),
        EventPattern('dbus-return', method='Claim'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

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

    # third_chan should not be closed
    q.unforbid_events(forbidden)
    forbidden.append(
        EventPattern('dbus-method-call',
                     method='Close',
                     path=third_chan.object_path))
    q.forbid_events(forbidden)

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
    )
    q.dbus_return(k.message, bus=kopete_bus, signature='')
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )
    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Kopete closes this one
    kopete_cdo = kopete_bus.get_object(cdo.bus_name, cdo.object_path)
    kopete_cdo_iface = dbus.Interface(kopete_cdo, cs.CDO)
    call_async(q, kopete_cdo_iface, 'Claim')

    q.expect_many(
        EventPattern('dbus-signal', path=cdo_path, signal='Finished'),
        EventPattern('dbus-signal',
                     path=cs.CD_PATH,
                     signal='DispatchOperationFinished',
                     args=[cdo_path]),
        EventPattern('dbus-return', method='Claim'),
    )

    # 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] == ''),
    )
    empathy_unique_name = e.args[1]

    empathy_bus.flush()
    empathy_bus.close()

    # In response, the channels that were being handled by Empathy are closed.
    # Kopete's channel is *not* closed.
    q.expect_many(
        EventPattern('dbus-signal',
                     signal='NameOwnerChanged',
                     predicate=(lambda e: e.args[0] == empathy_unique_name and
                                e.args[2] == '')),
        EventPattern('dbus-method-call', path=chan.object_path,
                     method='Close'),
        EventPattern('dbus-method-call',
                     path=claimed_chan.object_path,
                     method='Close'),
    )

    sync_dbus(bus, q, mc)
    q.unforbid_events(forbidden)
コード例 #6
0
def test_channel_creation(q,
                          bus,
                          account,
                          client,
                          conn,
                          yours_first=True,
                          swap_requests=False):
    user_action_time1 = dbus.Int64(1238582606)
    user_action_time2 = dbus.Int64(1244444444)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    # chat UI calls ChannelDispatcher.EnsureChannel
    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    call_async(q,
               cd,
               'EnsureChannel',
               account.object_path,
               request,
               user_action_time1,
               client.bus_name,
               dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='EnsureChannel')
    request_path = ret.value[0]

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

    cr1 = bus.get_object(cs.AM, request_path)
    request_props = cr1.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_time1
    assert request_props['PreferredHandler'] == client.bus_name
    assert request_props['Interfaces'] == []

    cr1.Proceed(dbus_interface=cs.CR)

    cm_request_call1, add_request_call1 = q.expect_many(
        EventPattern('dbus-method-call',
                     interface=cs.CONN_IFACE_REQUESTS,
                     method='EnsureChannel',
                     path=conn.object_path,
                     args=[request],
                     handled=False),
        EventPattern('dbus-method-call',
                     handled=False,
                     interface=cs.CLIENT_IFACE_REQUESTS,
                     method='AddRequest',
                     path=client.object_path),
    )

    # Before the first request has succeeded, the user gets impatient and
    # the UI re-requests.
    call_async(q,
               cd,
               'EnsureChannel',
               account.object_path,
               request,
               user_action_time2,
               client.bus_name,
               dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='EnsureChannel')
    request_path = ret.value[0]
    cr2 = bus.get_object(cs.AM, request_path)

    request_props = cr2.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_time2
    assert request_props['PreferredHandler'] == client.bus_name
    assert request_props['Interfaces'] == []

    cr2.Proceed(dbus_interface=cs.CR)

    cm_request_call2, add_request_call2 = q.expect_many(
        EventPattern('dbus-method-call',
                     interface=cs.CONN_IFACE_REQUESTS,
                     method='EnsureChannel',
                     path=conn.object_path,
                     args=[request],
                     handled=False),
        EventPattern('dbus-method-call',
                     handled=False,
                     interface=cs.CLIENT_IFACE_REQUESTS,
                     method='AddRequest',
                     path=client.object_path),
    )

    assert add_request_call1.args[0] == cr1.object_path
    request_props1 = add_request_call1.args[1]
    assert request_props1[cs.CR + '.Account'] == account.object_path
    assert request_props1[cs.CR + '.Requests'] == [request]
    assert request_props1[cs.CR + '.UserActionTime'] == user_action_time1
    assert request_props1[cs.CR + '.PreferredHandler'] == client.bus_name
    assert request_props1[cs.CR + '.Interfaces'] == []

    assert add_request_call2.args[0] == cr2.object_path
    request_props2 = add_request_call2.args[1]
    assert request_props2[cs.CR + '.Account'] == account.object_path
    assert request_props2[cs.CR + '.Requests'] == [request]
    assert request_props2[cs.CR + '.UserActionTime'] == user_action_time2
    assert request_props2[cs.CR + '.PreferredHandler'] == client.bus_name
    assert request_props2[cs.CR + '.Interfaces'] == []

    q.dbus_return(add_request_call1.message, signature='')
    q.dbus_return(add_request_call2.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)

    # Having announce() (i.e. NewChannels) come last is guaranteed by
    # telepathy-spec (since 0.17.14). There is no other ordering guarantee.

    if swap_requests:
        m2, m1 = cm_request_call1.message, cm_request_call2.message
    else:
        m1, m2 = cm_request_call1.message, cm_request_call2.message

    q.dbus_return(m1,
                  yours_first,
                  channel.object_path,
                  channel.immutable,
                  signature='boa{sv}')
    q.dbus_return(m2,
                  not yours_first,
                  channel.object_path,
                  channel.immutable,
                  signature='boa{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 sorted(e.args[4]) == sorted([cr1.object_path,
                                        cr2.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

    # 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 sorted(e.args[3]) == sorted([cr1.object_path,
                                        cr2.object_path]), e.args
    assert e.args[4] == user_action_time2, (e.args[4], user_action_time2)
    assert isinstance(e.args[5], dict)
    assertContains('request-properties', e.args[5])
    assertContains(cr1.object_path, e.args[5]['request-properties'])
    assertContains(cr2.object_path, e.args[5]['request-properties'])
    assertLength(2, e.args[5]['request-properties'])
    assertEquals(request_props1,
                 e.args[5]['request-properties'][cr1.object_path])
    assertEquals(request_props2,
                 e.args[5]['request-properties'][cr2.object_path])
    assert len(e.args) == 6

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

    return channel
def test(q, bus, unused, **kwargs):
    fake_accounts_service = kwargs['fake_accounts_service']
    preseed(q, bus, fake_accounts_service)

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

    user_action_time = dbus.Int64(1238582606)

    # A client and a CM are already running
    client = SimulatedClient(q, bus, 'Empathy',
            observe=[text_fixed_properties], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False,
            implement_get_interfaces=False)
    simulated_cm = SimulatedConnectionManager(q, bus)

    # service-activate MC; it will try to introspect the running client.
    mc = MC(q, bus, wait_for_names=False)
    get_interfaces, = mc.wait_for_names(
        EventPattern('dbus-method-call', path=client.object_path,
            interface=cs.PROPERTIES_IFACE, method='Get',
            args=[cs.CLIENT, 'Interfaces'],
            handled=False))

    # The client doesn't reply just yet; meanwhile, immediately make a channel
    # request
    account = bus.get_object(cs.MC,
            cs.tp_path_prefix +
            '/Account/fakecm/fakeprotocol/jc_2edenton_40unatco_2eint')
    cd = bus.get_object(cs.MC, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    request = dbus.Dictionary({
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': '*****@*****.**',
            }, signature='sv')
    call_async(q, cd, 'CreateChannel',
            account.object_path, request, user_action_time, client.bus_name,
            dbus_interface=cs.CD)

    ret = q.expect('dbus-return', method='CreateChannel')
    request_path = ret.value[0]

    # chat UI connects to signals and calls ChannelRequest.Proceed()
    cr = bus.get_object(cs.MC, 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'] == client.bus_name
    assert request_props['Interfaces'] == []

    call_async(q, cr, 'Proceed', dbus_interface=cs.CR)

    e = q.expect('dbus-method-call', method='RequestConnection',
            args=['fakeprotocol', {
                'account': '*****@*****.**',
                'password': '******',
                }],
            destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
            path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
            interface=cs.tp_name_prefix + '.ConnectionManager',
            handled=False)
    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', 'the_conn',
            '*****@*****.**')
    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    q.expect('dbus-method-call', method='Connect',
            path=conn.object_path, handled=True)
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)

    # A channel appears spontaneously

    announcement_immutable = dbus.Dictionary(text_fixed_properties)
    announcement_immutable[cs.CHANNEL + '.TargetID'] = '*****@*****.**'
    announcement_immutable[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, '*****@*****.**')
    announcement_immutable[cs.CHANNEL + '.InitiatorHandle'] = \
        announcement_immutable[cs.CHANNEL + '.TargetHandle']
    announcement_immutable[cs.CHANNEL + '.InitiatorID'] = \
        announcement_immutable[cs.CHANNEL + '.TargetID']
    announcement_immutable[cs.CHANNEL + '.Interfaces'] = \
            dbus.Array([], signature='s')
    announcement_immutable[cs.CHANNEL + '.Requested'] = False
    announcement = SimulatedChannel(conn, announcement_immutable)
    announcement.announce()

    # Now the Client returns its info
    q.dbus_return(get_interfaces.message,
            dbus.Array([cs.HANDLER, cs.OBSERVER, cs.APPROVER,
                cs.CLIENT_IFACE_REQUESTS], signature='s'), signature='v')

    expect_client_setup(q, [client], got_interfaces_already=True)

    # Now that the dispatcher is ready to go, we start looking for channels,
    # and also make the actual request
    # Empathy observes the channel we originally requested.
    _, a, cm_request_call = q.expect_many(
            EventPattern('dbus-method-call',
                interface=cs.PROPERTIES_IFACE, method='GetAll',
                args=[cs.CONN_IFACE_REQUESTS],
                path=conn.object_path, handled=True),
            EventPattern('dbus-method-call',
                path=client.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel',
                path=conn.object_path, args=[request], handled=False),
            )

    assert a.args[0] == account.object_path, a.args
    assert a.args[1] == conn.object_path, a.args
    assert a.args[3] != '/', a.args         # there is a dispatch operation
    assert a.args[4] == [], a.args
    channels = a.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == announcement.object_path, channels
    assert channels[0][1] == announcement_immutable, channels

    # 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, '*****@*****.**')
    channel = SimulatedChannel(conn, channel_immutable)

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

    # Empathy observes the newly-created channel.
    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(a.message, signature='')
    q.dbus_return(e.message, signature='')

    # Empathy is asked to handle the channel
    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
    assert e.args[4] == user_action_time
    assert isinstance(e.args[5], dict)
    assert len(e.args) == 6
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')

    # Empathy is an observer for text channels with
    # DelayApprovers=TRUE.
    empathy = SimulatedClient(q, bus, 'Empathy',
        observe=[text_fixed_properties], approve=[],
        handle=[], delay_approvers=True)

    # Kopete is an approver and handler for text channels.
    kopete = SimulatedClient(q, bus, 'Kopete',
        observe=[], approve=[text_fixed_properties],
        handle=[text_fixed_properties])

    expect_client_setup(q, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # A text channel appears!
    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()

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    # Empathy, the observer, gets the channel to observe. Because it
    # has DelayApprovers=TRUE, Kopete should not have
    # AddDispatchOperation called on it until Empathy returns from
    # ObserveChannels.
    forbidden = [EventPattern('dbus-method-call',
            path=kopete.object_path,
            interface=cs.APPROVER, method='AddDispatchOperation')]
    q.forbid_events(forbidden)

    o = q.expect('dbus-method-call',
             path=empathy.object_path,
             interface=cs.OBSERVER, method='ObserveChannels',
             handled=False)

    # Waste a little time here and there.  We can't call sync_dbus
    # here because it calls Ping and libdbus returns from Ping
    # synchronously and doesn't turn the main loop handle enough.
    call_async(q, cd_props, 'Get', cs.CD_IFACE_OP_LIST, 'DispatchOperations')
    event = q.expect('dbus-return', method='Get')

    # Finally return from ObserveChannels, so now we expect ADO to be
    # called on Kopete.
    q.dbus_return(o.message, bus=bus, signature='')
    q.unforbid_events(forbidden)

    e = q.expect('dbus-method-call',
             path=kopete.object_path,
             interface=cs.APPROVER, method='AddDispatchOperation',
             handled=False)

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

    # The user responds to Kopete
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Kopete')

    # Kopete is asked to handle the channels
    k = q.expect('dbus-method-call',
            path=kopete.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    # Kopete accepts the channels
    q.dbus_return(k.message, bus=bus, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
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)

    # One client (Kopete) has less specific filters than the other (Empathy),
    # to make sure that the dispatcher would normally prefer Empathy; this
    # means that when we use Kopete as the preferred handler, we know that
    # if Kopete is invoked, then preferring the preferred handler correctly
    # took precedence over the normal logic.
    vague_fixed_properties = dbus.Dictionary({
        cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        }, signature='sv')
    text_fixed_properties = dbus.Dictionary({
        cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
        cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        }, signature='sv')

    empathy_bus = dbus.bus.BusConnection()
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    q.attach_to_bus(kopete_bus)
    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q, empathy_bus, 'Empathy',
            observe=[text_fixed_properties], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)
    kopete = SimulatedClient(q, kopete_bus, 'Kopete',
            observe=[vague_fixed_properties], approve=[vague_fixed_properties],
            handle=[vague_fixed_properties], bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    # Empathy has a more specific filter, so it comes first
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention. However, the user is busy looking through the address
    # book, and independently decides to talk to Juliet. The address book
    # is from KDE so wants Kopete to be used.

    user_action_time = dbus.Int64(1238582606)

    request = dbus.Dictionary({
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
            }, signature='sv')
    call_async(q, cd, 'EnsureChannel',
            account.object_path, request, user_action_time, kopete.bus_name,
            dbus_interface=cs.CD)
    ret, add_request_call = q.expect_many(
            EventPattern('dbus-return', method='EnsureChannel'),
            EventPattern('dbus-method-call', handled=False,
                interface=cs.CLIENT_IFACE_REQUESTS,
                method='AddRequest', path=kopete.object_path),
            )
    request_path = ret.value[0]

    assert add_request_call.args[0] == request_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'] == kopete.bus_name
    assert request_props[cs.CR + '.Interfaces'] == []

    # 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'] == kopete.bus_name
    assert request_props['Interfaces'] == []

    cr.Proceed(dbus_interface=cs.CR)

    cm_request_call = q.expect('dbus-method-call',
            interface=cs.CONN_IFACE_REQUESTS,
            method='EnsureChannel',
            path=conn.object_path, args=[request], handled=False)

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

    # Time passes. The CM returns the existing channel

    q.dbus_return(cm_request_call.message, False,
            chan.object_path, chan.immutable, signature='boa{sv}')

    # EnsureChannel constitutes approval, so Kopete is told to handle the
    # channel

    e = q.expect('dbus-method-call',
            path=kopete.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] == chan.object_path, channels
    assert channels[0][1] == chan.immutable, channels
    assert e.args[3] == [request_path], e.args
    assert e.args[4] == user_action_time, (e.args[4], user_action_time)
    assert isinstance(e.args[5], dict)
    assert len(e.args) == 6

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

    q.expect_many(
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
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')

    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q, bus, 'Empathy',
            observe=[text_fixed_properties], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)
    kopete = SimulatedClient(q, bus, 'Kopete',
            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, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

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

    # The channel closes before Kopete has said yes. As a result, MC isn't
    # allowed to emit ChannelLost or Finished yet.
    chan.close()

    # Empathy wants to handle the channel, but is too late
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Empathy')
    e = q.expect('dbus-error')
    # FIXME: e.error.get_dbus_name() == [...Disconnected] which doesn't
    #   seem like the most appropriate thing for MC to do (but at least it's
    # consistent with ChannelLost)

    # *Now* Kopete is happy...

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

    # ... and in response, the channel dispatch operation finishes

    e = q.expect('dbus-signal', path=cdo_path, signal='ChannelLost')
    assert e.args[0] == chan.object_path
    # FIXME: e.args[1:] == [...Disconnected, 'Channel aborted'] which doesn't
    #   seem like the most appropriate thing for MC to do

    q.expect('dbus-signal', path=cdo_path, signal='Finished')
    q.expect('dbus-signal', path=cs.CD_PATH,
        signal='DispatchOperationFinished', args=[cdo_path])

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #11
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.RespawnObservers'
        },
        signature='sv')

    # Logger is an activatable Observer who will crash
    logger_bus = dbus.bus.BusConnection()
    logger_bus.set_exit_on_disconnect(False)  # we'll disconnect later

    # Kopete is an Approver, Handler and will not crash
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(logger_bus)
    q.attach_to_bus(kopete_bus)

    kopete = SimulatedClient(q,
                             kopete_bus,
                             'Kopete',
                             observe=[],
                             approve=[text_fixed_properties],
                             handle=[text_fixed_properties],
                             bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    k = q.expect('dbus-method-call',
                 path=kopete.object_path,
                 interface=cs.APPROVER,
                 method='AddDispatchOperation',
                 handled=False)

    assert k.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]

    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # The fake Logger implementation is run
    e = q.expect(
        'dbus-signal',
        path=cs.tp_path_prefix + '/RegressionTests',
        interface=cs.tp_name_prefix + '.RegressionTests',
        signal='FakeStartup',
        args=[cs.tp_name_prefix + '.Client.Logger'],
    )
    # We take on its identity to be able to continue with the test
    logger = SimulatedClient(q, bus, 'Logger', observe=[text_fixed_properties])

    # Logger is told about the new channel
    e = q.expect('dbus-method-call',
                 path=logger.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    # Logger indicates that it is ready to proceed
    q.dbus_return(e.message, bus=logger_bus, signature='')

    # The Approver (Kopete) is next

    # The user responds to Kopete
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Kopete')

    # Kopete is asked to handle the channels
    k = q.expect('dbus-method-call',
                 path=kopete.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)

    # Kopete accepts the channels
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWith'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Logger crashes
    logger.release_name()

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

    logger_bus.flush()

    # Logger gets restart request
    e = q.expect(
        'dbus-signal',
        path=cs.tp_path_prefix + '/RegressionTests',
        interface=cs.tp_name_prefix + '.RegressionTests',
        signal='FakeStartup',
        args=[cs.tp_name_prefix + '.Client.Logger'],
    )

    # Logger gets restarted
    logger.reacquire_name()

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

    e = q.expect('dbus-method-call',
                 path=logger.object_path,
                 interface=cs.OBSERVER,
                 method='ObserveChannels',
                 handled=False)

    # FIXME: assert the same things as before, except CDO (which we don't
    # have) and account path (which we don't know how to get); also check
    # that the recovering observer info key is set
    assert e.args[0] == account.object_path, e.args
    assert e.args[1] == conn.object_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    assert e.args[5]['recovering'] == 1, e.args  # due to observer recovery
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    # Logger indicates that it is ready to proceed
    q.dbus_return(e.message, bus=logger_bus, signature='')

    sync_dbus(bus, q, mc)
コード例 #12
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')
    voip_fixed_properties = dbus.Dictionary({
        cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
        cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL,
        }, signature='sv')

    # Two clients want to observe, approve and handle text and VoIP channels.
    empathy = SimulatedClient(q, bus, 'Empathy',
            observe=[text_fixed_properties, voip_fixed_properties],
            approve=[text_fixed_properties, voip_fixed_properties],
            handle=[text_fixed_properties, voip_fixed_properties],
            bypass_approval=False)
    kopete = SimulatedClient(q, bus, 'Kopete',
            observe=[text_fixed_properties, voip_fixed_properties],
            approve=[text_fixed_properties, voip_fixed_properties],
            handle=[text_fixed_properties, voip_fixed_properties],
            bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # First, a VoIP channel is created

    BUNDLE = '/8de0d29d-83e1-40f5-b24f-748c0aa86c82'

    channel_properties = dbus.Dictionary(voip_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')
    channel_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

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

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Now that Empathy has the VoIP channel, it wants to steal incoming Text
    # channels from the same bundle

    same_bundle_properties = dbus.Dictionary(text_fixed_properties,
            signature='sv')
    same_bundle_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE

    bypass = SimulatedClient(q, bus, 'Empathy._1_42.Window2',
            observe=[],
            approve=[],
            handle=[same_bundle_properties],
            bypass_approval=True)

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

    # From now on, this test must fail if we're asked to approve anything
    approval = [
            EventPattern('dbus-method-call', method='AddDispatchOperation'),
            ]
    q.forbid_events(approval)

    channel_properties = dbus.Dictionary(text_fixed_properties,
            signature='sv')
    channel_properties[cs.CHANNEL + '.TargetHandleType'] = cs.HT_CONTACT
    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 + '.FUTURE.Bundle'] = BUNDLE
    channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

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

    # Again, there's a CDO

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    # The handler with BypassApproval is first
    assert handlers[0] == bypass.bus_name
    # The other two handlers are still possibilities
    assert len(handlers) == 3

    # Observers are invoked as usual

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # Empathy's BypassApproval part is asked to handle the channels
    e = q.expect('dbus-method-call',
            path=bypass.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)
    # Empathy accepts the channels
    q.dbus_return(e.message, signature='')
コード例 #14
0
    q.dbus_return(add_request_call.message, signature='')

    # Actually, never mind.
    cr.Cancel(dbus_interface=cs.CR)

    # 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',
コード例 #15
0
def test_dispatching(q, bus, conn, account, empathy, kopete):
    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    ops = cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations')
    assert ops == [], ops

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWith'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
def test_channel_creation(q, bus, account, client, conn, ensure):
    user_action_time = dbus.Int64(1238582606)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    # chat UI calls ChannelDispatcher.EnsureChannel or CreateChannel
    request = dbus.Dictionary({
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
            }, signature='sv')
    call_async(q, cd,
            (ensure and 'EnsureChannel' or 'CreateChannel'),
            account.object_path, request, user_action_time, "",
            dbus_interface=cs.CD)
    ret = q.expect('dbus-return',
            method=(ensure and 'EnsureChannel' or 'CreateChannel'))
    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'] == ""
    assert request_props['Interfaces'] == []

    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', path=client.object_path),
            )

    assert add_request_call.args[0] == request_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'] == ""
    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()

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

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

    # Close the channel
    channel.close()
コード例 #17
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')

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

    misc_fixed_properties = dbus.Dictionary({
        cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
        cs.CHANNEL + '.ChannelType': 'com.example.Extension',
        }, signature='sv')

    # Two clients want to observe, approve and handle channels. Empathy handles
    # VoIP, Kopete does not.
    empathy = SimulatedClient(q, bus, 'org.gnome.Empathy',
            observe=[text_fixed_properties, media_fixed_properties],
            approve=[text_fixed_properties, media_fixed_properties],
            handle=[text_fixed_properties, media_fixed_properties],
            bypass_approval=False)

    kopete = SimulatedClient(q, bus, 'org.kde.Kopete',
            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, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Part 1. A bundle that Empathy, but not Kopete, can handle

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

    text_chan = SimulatedChannel(conn, text_channel_properties,
            destroyable=True)

    media_channel_properties = dbus.Dictionary(media_fixed_properties,
            signature='sv')
    media_channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet'
    media_channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    media_channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet'
    media_channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    media_channel_properties[cs.CHANNEL + '.Requested'] = False
    media_channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(
            signature='s')

    media_chan = SimulatedChannel(conn, media_channel_properties,
            destroyable=False)

    conn.NewChannels([text_chan, media_chan])

    # A channel dispatch operation is created for the Text channel first.

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    text_cdo_path = e.args[0]
    text_cdo_properties = e.args[1]

    assert text_cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert text_cdo_properties[cs.CDO + '.Connection'] == conn.object_path

    handlers = text_cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    assert (sorted(handlers) ==
        [cs.tp_name_prefix + '.Client.org.gnome.Empathy',
            cs.tp_name_prefix + '.Client.org.kde.Kopete']), handlers

    text_cdo = bus.get_object(cs.CD, text_cdo_path)
    text_cdo_iface = dbus.Interface(text_cdo, cs.CDO)

    # Both Observers are told about the new Text channel

    e_observe_text, k_observe_text = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            )
    assert e_observe_text.args[0] == account.object_path, e_observe_text.args
    assert e_observe_text.args[1] == conn.object_path, e_observe_text.args
    assert e_observe_text.args[3] == text_cdo_path, e_observe_text.args
    assert e_observe_text.args[4] == [], e_observe_text.args
    channels = e_observe_text.args[2]
    assert len(channels) == 1, channels
    assert (text_chan.object_path, text_channel_properties) in channels

    assert k_observe_text.args[0] == e_observe_text.args[0], k_observe_text.args
    assert k_observe_text.args[1] == e_observe_text.args[1], k_observe_text.args
    assert (k_observe_text.args[2] ==
            [(text_chan.object_path, text_channel_properties)])

    # Now a separate CDO is created for the media channel.

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    media_cdo_path = e.args[0]
    media_cdo_properties = e.args[1]

    assert media_cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert media_cdo_properties[cs.CDO + '.Connection'] == conn.object_path

    handlers = media_cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    # only Empathy can handle it
    assert (sorted(handlers) ==
        [cs.tp_name_prefix + '.Client.org.gnome.Empathy']), handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert (sorted(cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations')) ==
            [(text_cdo_path, text_cdo_properties),
                (media_cdo_path, media_cdo_properties)])

    media_cdo = bus.get_object(cs.CD, media_cdo_path)
    media_cdo_iface = dbus.Interface(media_cdo, cs.CDO)

    # Only Empathy is told about the new media channel

    e_observe_media = q.expect('dbus-method-call',
            path=empathy.object_path,
            interface=cs.OBSERVER, method='ObserveChannels',
            handled=False)
    assert e_observe_media.args[0] == account.object_path, e_observe_media.args
    assert e_observe_media.args[1] == conn.object_path, e_observe_media.args
    assert e_observe_media.args[3] == media_cdo_path, e_observe_media.args
    assert e_observe_media.args[4] == [], e_observe_media.args
    channels = e_observe_media.args[2]
    assert len(channels) == 1, channels
    assert (media_chan.object_path, media_channel_properties) in channels

    # All Observers reply.

    q.dbus_return(e_observe_text.message, signature='')
    q.dbus_return(k_observe_text.message, signature='')
    q.dbus_return(e_observe_media.message, signature='')

    # The Approvers are next
    e_approve_text, k_approve_text, e_approve_media = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                predicate=lambda e: e.args[1] == text_cdo_path,
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                predicate=lambda e: e.args[1] == media_cdo_path,
                handled=False)
            )
    assert len(e_approve_text.args[0]) == 1
    assert ((text_chan.object_path, text_channel_properties) in
            e_approve_text.args[0])
    assert e_approve_text.args[1:] == [text_cdo_path, text_cdo_properties]
    assert k_approve_text.args == e_approve_text.args

    assert len(e_approve_media.args[0]) == 1
    assert ((media_chan.object_path, media_channel_properties) in
            e_approve_media.args[0])
    assert e_approve_media.args[1:] == [media_cdo_path, media_cdo_properties]

    q.dbus_return(e_approve_text.message, signature='')
    q.dbus_return(k_approve_text.message, signature='')
    q.dbus_return(e_approve_media.message, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention. The user clicks on Empathy
    call_async(q, text_cdo_iface, 'HandleWith',
        cs.tp_name_prefix + '.Client.org.gnome.Empathy')

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

    # Empathy accepts the channel
    q.dbus_return(e.message, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # The user doesn't care which client will handle the channel - because
    # Empathy is the only possibility, it will be chosen (this is also a
    # regression test for the ability to leave the handler unspecified).
    call_async(q, media_cdo_iface, 'HandleWith', '')

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

    # Empathy accepts the channel
    q.dbus_return(e.message, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    text_chan.close()
    media_chan.close()

    # Part 2. A bundle that neither client can handle in its entirety

    respawning_channel_properties = dbus.Dictionary(misc_fixed_properties,
            signature='sv')
    respawning_channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet'
    respawning_channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    respawning_channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet'
    respawning_channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    respawning_channel_properties[cs.CHANNEL + '.Requested'] = False
    respawning_channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(
            [cs.CHANNEL_IFACE_DESTROYABLE], signature='s')

    ext_channel_properties = dbus.Dictionary(misc_fixed_properties,
            signature='sv')
    ext_channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet'
    ext_channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    ext_channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet'
    ext_channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'juliet')
    ext_channel_properties[cs.CHANNEL + '.Requested'] = False
    ext_channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(
            signature='s')

    text_chan = SimulatedChannel(conn, text_channel_properties,
            destroyable=True)
    media_chan = SimulatedChannel(conn, media_channel_properties,
            destroyable=False)
    respawning_chan = SimulatedChannel(conn, respawning_channel_properties,
            destroyable=True)
    ext_chan = SimulatedChannel(conn, ext_channel_properties,
            destroyable=False)

    conn.NewChannels([text_chan, media_chan, ext_chan, respawning_chan])

    # No client can handle all four channels, so the bundle explodes into
    # two dispatch operations and two failures. We can only match the first
    # CDO here - we look at the others later.
    e_observe_media, e_observe_text, k_observe_text, \
    e_approve_media, e_approve_text, k_approve_text, \
    _, _, _ = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                predicate=(lambda e: e.args[2][0][0] == media_chan.object_path),
                handled=False),
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                predicate=(lambda e: e.args[2][0][0] == text_chan.object_path),
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                predicate=(lambda e: e.args[2][0][0] == text_chan.object_path),
                handled=False),
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                predicate=(lambda e:
                    e.args[0][0][0] ==
                    media_chan.object_path),
                handled=False),
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                predicate=(lambda e:
                    e.args[0][0][0] ==
                    text_chan.object_path),
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                predicate=(lambda e:
                    e.args[0][0][0] ==
                    text_chan.object_path),
                handled=False),
            EventPattern('dbus-method-call',
                interface=cs.CHANNEL_IFACE_DESTROYABLE,
                method='Destroy',
                path=respawning_chan.object_path,
                handled=True),
            EventPattern('dbus-method-call',
                interface=cs.CHANNEL,
                method='Close',
                path=ext_chan.object_path,
                handled=True),
            # we can't distinguish between the two NewDispatchOperation signals
            # since we no longer see the Channels property (it's mutable)
            EventPattern('dbus-signal',
                path=cs.CD_PATH,
                interface=cs.CD_IFACE_OP_LIST,
                signal='NewDispatchOperation'),
            )

    q.dbus_return(e_observe_media.message, signature='')
    q.dbus_return(e_observe_text.message, signature='')
    q.dbus_return(k_observe_text.message, signature='')
    q.dbus_return(e_approve_media.message, signature='')
    q.dbus_return(e_approve_text.message, signature='')
    q.dbus_return(k_approve_text.message, signature='')
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 + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
        }, signature='sv')

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

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

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

    forbidden = [
            EventPattern('dbus-method-call', method='AddDispatchOperation'),
            ]
    q.forbid_events(forbidden)

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

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    assertEquals([], handlers)

    e = q.expect('dbus-method-call',
            path=client.object_path,
            interface=cs.OBSERVER, method='ObserveChannels',
            handled=False)

    sync_dbus(bus, q, mc)

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

    # now (but only now) MC kills the channel
    q.expect_many(
            EventPattern('dbus-signal', path=cdo_path, signal='Finished'),
            EventPattern('dbus-method-call', path=chan.object_path,
                method='Close', handled=True),
            )

    # There are no active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #19
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')

    empathy_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    empathy = SimulatedClient(q, empathy_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, [empathy])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    e = q.expect('dbus-method-call',
            path=empathy.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

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

    e = q.expect('dbus-method-call',
            path=empathy.object_path,
            interface=cs.APPROVER, method='AddDispatchOperation',
            handled=False)

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]

    # Empathy rejects the channels
    q.dbus_raise(e.message, cs.NOT_AVAILABLE, 'Blind drunk', bus=empathy_bus)

    # No approver works, so Empathy-the-Handler is asked to handle the channels
    e = q.expect('dbus-method-call',
            path=empathy.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    # Empathy rejects the channels
    q.dbus_raise(e.message, cs.NOT_AVAILABLE, 'Still drunk', bus=empathy_bus)

    q.expect_many(
            EventPattern('dbus-method-call', path=chan.object_path,
                interface=cs.CHANNEL, method='Close', handled=True),
            EventPattern('dbus-signal', path=cdo.object_path,
                interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', path=cd.object_path,
                interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #20
0
def announce_common(q,
                    bus,
                    empathy,
                    kopete,
                    account,
                    conn,
                    cd_props,
                    urgent=False):
    if urgent:
        jid = 'friar.lawrence'
    else:
        jid = 'juliet'

    channel_properties = dbus.Dictionary(contact_text_fixed_properties,
                                         signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = jid
    channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, jid)
    channel_properties[cs.CHANNEL + '.InitiatorID'] = jid
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, jid)
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

    if urgent:
        channel_properties['com.example.Urgency.Urgent'] = True

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]

    if urgent:
        # The handler with BypassApproval is first
        assert handlers[
            0] == cs.tp_name_prefix + '.Client.Kopete.BypassApproval'
        # Kopete's filter is more specific than Empathy's, so it comes next
        assert handlers[1] == cs.tp_name_prefix + '.Client.Kopete'
        # Empathy's filter is the least specific, so it's last
        assert handlers[2] == cs.tp_name_prefix + '.Client.Empathy'
        assert len(handlers) == 3
    else:
        handlers.sort()
        assert handlers == [
            cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'
        ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    return cdo_iface, chan, channel_properties, [e, k]
コード例 #21
0
def test(q, bus, unused, **kwargs):
    fake_accounts_service = kwargs['fake_accounts_service']
    preseed(q, bus, fake_accounts_service)

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

    user_action_time = dbus.Int64(1238582606)

    # A client and a CM are already running
    client = SimulatedClient(q,
                             bus,
                             'Empathy',
                             observe=[text_fixed_properties],
                             approve=[text_fixed_properties],
                             handle=[text_fixed_properties],
                             bypass_approval=False,
                             implement_get_interfaces=False)
    simulated_cm = SimulatedConnectionManager(q, bus)

    # service-activate MC; it will try to introspect the running client.
    mc = MC(q, bus, wait_for_names=False)
    get_interfaces, = mc.wait_for_names(
        EventPattern('dbus-method-call',
                     path=client.object_path,
                     interface=cs.PROPERTIES_IFACE,
                     method='Get',
                     args=[cs.CLIENT, 'Interfaces'],
                     handled=False))

    # The client doesn't reply just yet; meanwhile, immediately make a channel
    # request
    account = bus.get_object(
        cs.MC, cs.tp_path_prefix +
        '/Account/fakecm/fakeprotocol/jc_2edenton_40unatco_2eint')
    cd = bus.get_object(cs.MC, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': '*****@*****.**',
        },
        signature='sv')
    call_async(q,
               cd,
               'CreateChannel',
               account.object_path,
               request,
               user_action_time,
               client.bus_name,
               dbus_interface=cs.CD)

    ret = q.expect('dbus-return', method='CreateChannel')
    request_path = ret.value[0]

    # chat UI connects to signals and calls ChannelRequest.Proceed()
    cr = bus.get_object(cs.MC, 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'] == client.bus_name
    assert request_props['Interfaces'] == []

    call_async(q, cr, 'Proceed', dbus_interface=cs.CR)

    e = q.expect('dbus-method-call',
                 method='RequestConnection',
                 args=[
                     'fakeprotocol', {
                         'account': '*****@*****.**',
                         'password': '******',
                     }
                 ],
                 destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
                 path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
                 interface=cs.tp_name_prefix + '.ConnectionManager',
                 handled=False)
    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', 'the_conn',
                               '*****@*****.**')
    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    q.expect('dbus-method-call',
             method='Connect',
             path=conn.object_path,
             handled=True)
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)

    # A channel appears spontaneously

    announcement_immutable = dbus.Dictionary(text_fixed_properties)
    announcement_immutable[cs.CHANNEL + '.TargetID'] = '*****@*****.**'
    announcement_immutable[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, '*****@*****.**')
    announcement_immutable[cs.CHANNEL + '.InitiatorHandle'] = \
        announcement_immutable[cs.CHANNEL + '.TargetHandle']
    announcement_immutable[cs.CHANNEL + '.InitiatorID'] = \
        announcement_immutable[cs.CHANNEL + '.TargetID']
    announcement_immutable[cs.CHANNEL + '.Interfaces'] = \
            dbus.Array([], signature='s')
    announcement_immutable[cs.CHANNEL + '.Requested'] = False
    announcement = SimulatedChannel(conn, announcement_immutable)
    announcement.announce()

    # Now the Client returns its info
    q.dbus_return(
        get_interfaces.message,
        dbus.Array(
            [cs.HANDLER, cs.OBSERVER, cs.APPROVER, cs.CLIENT_IFACE_REQUESTS],
            signature='s'),
        signature='v')

    expect_client_setup(q, [client], got_interfaces_already=True)

    # Now that the dispatcher is ready to go, we start looking for channels,
    # and also make the actual request
    # Empathy observes the channel we originally requested.
    _, a, cm_request_call = q.expect_many(
        EventPattern('dbus-method-call',
                     interface=cs.PROPERTIES_IFACE,
                     method='GetAll',
                     args=[cs.CONN_IFACE_REQUESTS],
                     path=conn.object_path,
                     handled=True),
        EventPattern('dbus-method-call',
                     path=client.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     interface=cs.CONN_IFACE_REQUESTS,
                     method='CreateChannel',
                     path=conn.object_path,
                     args=[request],
                     handled=False),
    )

    assert a.args[0] == account.object_path, a.args
    assert a.args[1] == conn.object_path, a.args
    assert a.args[3] != '/', a.args  # there is a dispatch operation
    assert a.args[4] == [], a.args
    channels = a.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == announcement.object_path, channels
    assert channels[0][1] == announcement_immutable, channels

    # 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, '*****@*****.**')
    channel = SimulatedChannel(conn, channel_immutable)

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

    # Empathy observes the newly-created channel.
    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(a.message, signature='')
    q.dbus_return(e.message, signature='')

    # Empathy is asked to handle the channel
    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
    assert e.args[4] == user_action_time
    assert isinstance(e.args[5], dict)
    assert len(e.args) == 6
コード例 #22
0
def test(q, bus, mc):
    params = dbus.Dictionary(
        {
            "account": "*****@*****.**",
            "password": "******"
        },
        signature='sv')
    (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)

    account_iface = dbus.Interface(account, cs.ACCOUNT)
    account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)

    # Ensure that it's enabled but has offline RP and doesn't connect
    # automatically

    verification_filter = dbus.Dictionary(
        {
            cs.CHANNEL + '.TargetHandleType': 0,
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION,
        },
        signature='sv')

    verifier_bus = dbus.bus.BusConnection()
    q.attach_to_bus(verifier_bus)
    verifier = SimulatedClient(q,
                               verifier_bus,
                               'Verifier',
                               handle=[verification_filter])

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

    account_props.Set(cs.ACCOUNT, 'RequestedPresence',
                      (dbus.UInt32(cs.PRESENCE_AVAILABLE), 'available', ''))

    account_props.Set(cs.ACCOUNT, 'Enabled', True)

    e = q.expect('dbus-method-call',
                 method='RequestConnection',
                 args=['fakeprotocol', params],
                 destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
                 path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
                 interface=cs.tp_name_prefix + '.ConnectionManager',
                 handled=False)

    conn = SimulatedConnection(q,
                               bus,
                               'fakecm',
                               'fakeprotocol',
                               '_',
                               'myself',
                               has_presence=True)

    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    e = q.expect('dbus-method-call',
                 method='Connect',
                 path=conn.object_path,
                 interface=cs.CONN)

    channel_properties = dbus.Dictionary(verification_filter, signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = ''
    channel_properties[cs.CHANNEL + '.TargetHandle'] = 0
    channel_properties[cs.CHANNEL + '.InitiatorID'] = ''
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = 0
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array([],
                                                                signature='s')

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

    e = q.expect('dbus-method-call',
                 path=verifier.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)
コード例 #23
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')
    voip_fixed_properties = dbus.Dictionary(
        {
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL,
        },
        signature='sv')

    # Two clients want to observe, approve and handle text and VoIP channels.
    empathy = SimulatedClient(
        q,
        bus,
        'Empathy',
        observe=[text_fixed_properties, voip_fixed_properties],
        approve=[text_fixed_properties, voip_fixed_properties],
        handle=[text_fixed_properties, voip_fixed_properties],
        bypass_approval=False)
    kopete = SimulatedClient(
        q,
        bus,
        'Kopete',
        observe=[text_fixed_properties, voip_fixed_properties],
        approve=[text_fixed_properties, voip_fixed_properties],
        handle=[text_fixed_properties, voip_fixed_properties],
        bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # First, a VoIP channel is created

    BUNDLE = '/8de0d29d-83e1-40f5-b24f-748c0aa86c82'

    channel_properties = dbus.Dictionary(voip_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')
    channel_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

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

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWith'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Now that Empathy has the VoIP channel, it wants to steal incoming Text
    # channels from the same bundle

    same_bundle_properties = dbus.Dictionary(text_fixed_properties,
                                             signature='sv')
    same_bundle_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE

    bypass = SimulatedClient(q,
                             bus,
                             'Empathy._1_42.Window2',
                             observe=[],
                             approve=[],
                             handle=[same_bundle_properties],
                             bypass_approval=True)

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

    # From now on, this test must fail if we're asked to approve anything
    approval = [
        EventPattern('dbus-method-call', method='AddDispatchOperation'),
    ]
    q.forbid_events(approval)

    channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv')
    channel_properties[cs.CHANNEL + '.TargetHandleType'] = cs.HT_CONTACT
    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 + '.FUTURE.Bundle'] = BUNDLE
    channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

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

    # Again, there's a CDO

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    # The handler with BypassApproval is first
    assert handlers[0] == bypass.bus_name
    # The other two handlers are still possibilities
    assert len(handlers) == 3

    # Observers are invoked as usual

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # Empathy's BypassApproval part is asked to handle the channels
    e = q.expect('dbus-method-call',
                 path=bypass.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)
    # Empathy accepts the channels
    q.dbus_return(e.message, signature='')
コード例 #24
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')

    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q,
                              bus,
                              'Empathy',
                              observe=[text_fixed_properties],
                              approve=[text_fixed_properties],
                              handle=[text_fixed_properties],
                              bypass_approval=False)
    kopete = SimulatedClient(q,
                             bus,
                             'Kopete',
                             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, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

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

    # The channel closes before Kopete has said yes. As a result, MC isn't
    # allowed to emit ChannelLost or Finished yet.
    chan.close()

    # Empathy wants to handle the channel, but is too late
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Empathy')
    e = q.expect('dbus-error')
    # FIXME: e.error.get_dbus_name() == [...Disconnected] which doesn't
    #   seem like the most appropriate thing for MC to do (but at least it's
    # consistent with ChannelLost)

    # *Now* Kopete is happy...

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

    # ... and in response, the channel dispatch operation finishes

    e = q.expect('dbus-signal', path=cdo_path, signal='ChannelLost')
    assert e.args[0] == chan.object_path
    # FIXME: e.args[1:] == [...Disconnected, 'Channel aborted'] which doesn't
    #   seem like the most appropriate thing for MC to do

    q.expect('dbus-signal', path=cdo_path, signal='Finished')
    q.expect('dbus-signal',
             path=cs.CD_PATH,
             signal='DispatchOperationFinished',
             args=[cdo_path])

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
def announce_common(q, bus, empathy, kopete, account, conn, cd_props,
        urgent=False):
    if urgent:
        jid = 'friar.lawrence'
    else:
        jid = 'juliet'

    channel_properties = dbus.Dictionary(contact_text_fixed_properties,
            signature='sv')
    channel_properties[cs.CHANNEL + '.TargetID'] = jid
    channel_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, jid)
    channel_properties[cs.CHANNEL + '.InitiatorID'] = jid
    channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, jid)
    channel_properties[cs.CHANNEL + '.Requested'] = False
    channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

    if urgent:
        channel_properties['com.example.Urgency.Urgent'] = True

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]

    if urgent:
        # The handler with BypassApproval is first
        assert handlers[0] == cs.tp_name_prefix + '.Client.Kopete.BypassApproval'
        # Kopete's filter is more specific than Empathy's, so it comes next
        assert handlers[1] == cs.tp_name_prefix + '.Client.Kopete'
        # Empathy's filter is the least specific, so it's last
        assert handlers[2] == cs.tp_name_prefix + '.Client.Empathy'
        assert len(handlers) == 3
    else:
        handlers.sort()
        assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
                cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    return cdo_iface, chan, channel_properties, [e, k]
def test(q, bus, mc):
    params = dbus.Dictionary({"account": "*****@*****.**",
        "password": "******"}, signature='sv')
    (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)

    account_iface = dbus.Interface(account, cs.ACCOUNT)
    account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)

    # Ensure that it's enabled but has offline RP and doesn't connect
    # automatically

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
            (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
    q.expect('dbus-return', method='Set')

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence',
            (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
                'Testing automatic presence'))
    q.expect('dbus-return', method='Set')
    q.expect('dbus-signal', signal='AccountPropertyChanged',
            predicate=lambda e:
                e.args[0].get('AutomaticPresence', (None, None, None))[1]
                    == 'busy')

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'ConnectAutomatically',
            False)
    q.expect('dbus-return', method='Set')

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'Enabled', True)
    q.expect('dbus-return', method='Set')
    q.expect('dbus-signal', signal='AccountPropertyChanged',
            predicate=lambda e: e.args[0].get('Enabled'))

    # Requesting a channel will put us online

    user_action_time = dbus.Int64(1238582606)

    cd = bus.get_object(cs.CD, cs.CD_PATH)

    request = dbus.Dictionary({
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
            }, signature='sv')
    call_async(q, cd, 'CreateChannel',
            account.object_path, request, user_action_time, "",
            dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='CreateChannel')
    request_path = ret.value[0]

    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'] == ""
    assert request_props['Interfaces'] == []

    # make sure RequestConnection doesn't get called until we Proceed
    events = [EventPattern('dbus-method-call', method='RequestConnection')]
    q.forbid_events(events)

    sync_dbus(bus, q, mc)

    q.unforbid_events(events)

    cr.Proceed(dbus_interface=cs.CR)

    e = q.expect('dbus-method-call', method='RequestConnection',
            args=['fakeprotocol', params],
            destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
            path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
            interface=cs.tp_name_prefix + '.ConnectionManager',
            handled=False)

    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
            'myself', has_presence=True)

    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    q.expect('dbus-method-call', method='Connect',
            path=conn.object_path, handled=True)
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
    conn.presence = dbus.Struct((cs.PRESENCE_AVAILABLE, 'available', ''),
            signature='uss')

    _, cm_request_call = q.expect_many(
            EventPattern('dbus-method-call', path=conn.object_path,
                interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence',
                args=['busy', 'Testing automatic presence'], handled=True),
            EventPattern('dbus-method-call', path=conn.object_path,
                interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel',
                args=[request], handled=False),
            )

    q.dbus_emit(conn.object_path, cs.CONN_IFACE_SIMPLE_PRESENCE,
            'PresencesChanged',
            {conn.self_handle: (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
                'Testing automatic presence')},
            signature='a{u(uss)}')

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

    # there's no handler, so it gets shot down

    q.expect('dbus-method-call', path=channel.object_path, method='Close',
            handled=True)
コード例 #27
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 + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
        },
        signature='sv')

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

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

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

    forbidden = [
        EventPattern('dbus-method-call', method='AddDispatchOperation'),
    ]
    q.forbid_events(forbidden)

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

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    assertEquals([], handlers)

    e = q.expect('dbus-method-call',
                 path=client.object_path,
                 interface=cs.OBSERVER,
                 method='ObserveChannels',
                 handled=False)

    sync_dbus(bus, q, mc)

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

    # now (but only now) MC kills the channel
    q.expect_many(
        EventPattern('dbus-signal', path=cdo_path, signal='Finished'),
        EventPattern('dbus-method-call',
                     path=chan.object_path,
                     method='Close',
                     handled=True),
    )

    # There are no active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #28
0
def test(q, bus, mc):
    http_fixed_properties = dbus.Dictionary({
        cs.CHANNEL + '.TargetHandleType': 1L,
        cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAM_TUBE,
        cs.CHANNEL_TYPE_STREAM_TUBE + '.Service':
            'http'
        }, signature='sv')
    caps = dbus.Array([http_fixed_properties], signature='a{sv}')

    # Be a Client
    client = SimulatedClient(q, bus, 'downloader',
            observe=[], approve=[], handle=[http_fixed_properties],
            bypass_approval=False)
    expect_client_setup(q, [client])

    # Create an account
    params = dbus.Dictionary({"account": "*****@*****.**",
        "password": "******"}, signature='sv')
    (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)

    # The account is initially valid but disabled, and hence offline
    props = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE)
    assert not props['Enabled']
    assert props['Valid']
    # The spec says it should be (Offline, "", "") but I don't think the
    # strings really matter. If anything, the second one should start out at
    # "offline".
    assertEquals(cs.PRESENCE_OFFLINE, props['CurrentPresence'][0])

    # Enable the account
    account.Set(cs.ACCOUNT, 'Enabled', True,
            dbus_interface=cs.PROPERTIES_IFACE)
    q.expect('dbus-signal',
            path=account.object_path,
            signal='AccountPropertyChanged',
            interface=cs.ACCOUNT)

    props = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE)
    assert props['Enabled']
    assert props['Valid']
    # Ditto above re. string fields.
    assertEquals(cs.PRESENCE_OFFLINE, props['CurrentPresence'][0])

    # Go online
    requested_presence = dbus.Struct((dbus.UInt32(2L), dbus.String(u'brb'),
                dbus.String(u'Be back soon!')))
    account.Set(cs.ACCOUNT,
            'RequestedPresence', requested_presence,
            dbus_interface=cs.PROPERTIES_IFACE)

    e = q.expect('dbus-method-call', method='RequestConnection',
            args=['fakeprotocol', params],
            destination=tp_name_prefix + '.ConnectionManager.fakecm',
            path=tp_path_prefix + '/ConnectionManager/fakecm',
            interface=tp_name_prefix + '.ConnectionManager',
            handled=False)

    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
            'myself')

    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    # MC does some setup, including fetching the list of Channels

    q.expect_many(
            EventPattern('dbus-method-call',
                interface=cs.PROPERTIES_IFACE, method='GetAll',
                args=[cs.CONN_IFACE_REQUESTS],
                path=conn.object_path, handled=True),
            )

    # MC prepares the connection, does any pre-Connect setup, then
    # calls Connect
    q.expect('dbus-method-call', method='Connect',
            path=conn.object_path, handled=True)

    # Connect succeeds
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)

    # Assert that the NormalizedName is harvested from the Connection at some
    # point
    while 1:
        e = q.expect('dbus-signal',
                interface=cs.ACCOUNT, signal='AccountPropertyChanged',
                path=account.object_path)
        if 'NormalizedName' in e.args[0]:
            assert e.args[0]['NormalizedName'] == 'myself', e.args
            break

    # Check the requested presence is online
    properties = account.GetAll(cs.ACCOUNT,
            dbus_interface=cs.PROPERTIES_IFACE)
    assert properties is not None
    assert properties.get('HasBeenOnline')
    assertEquals(requested_presence, properties.get('RequestedPresence'))

    # Since this Connection doesn't support SimplePresence, but it's online,
    # the spec says that CurrentPresence should be Unset.
    assertEquals((cs.PRESENCE_UNSET, "", ""),
        properties.get('CurrentPresence'))

    new_channel = http_fixed_properties
    buddy_handle = conn.ensure_handle(cs.HT_CONTACT, "buddy")
    new_channel[cs.CHANNEL + '.TargetID'] = "buddy"
    new_channel[cs.CHANNEL + '.TargetHandle'] = buddy_handle
    new_channel[cs.CHANNEL + '.Requested'] = False
    new_channel[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

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

    e = q.expect('dbus-method-call', method='HandleChannels')
    q.dbus_return(e.message, signature='')

    # Put the account offline
    requested_presence = (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', '')
    account.Set(cs.ACCOUNT,
            'RequestedPresence', requested_presence,
            dbus_interface=cs.PROPERTIES_IFACE)

    # In response, MC tells us to Disconnect, and we do. But it should not
    # Close() the open channel.
    q.forbid_events([
        EventPattern('dbus-method-call', method='Close', path=conn.object_path),
        ])
    q.expect('dbus-method-call', method='Disconnect',
            path=conn.object_path, handled=True)

    properties = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE)
    assertEquals('/', properties['Connection'])
    assertEquals(cs.CONN_STATUS_DISCONNECTED, properties['ConnectionStatus'])
    assertEquals(requested_presence, properties['CurrentPresence'])
    assertEquals(requested_presence, properties['RequestedPresence'])
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),
            )
コード例 #30
0
def test_channel_creation(q, bus, account, client, conn):
    user_action_time = dbus.Int64(1238582606)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    # chat UI calls ChannelDispatcher.EnsureChannel
    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    call_async(q,
               cd,
               'EnsureChannel',
               account.object_path,
               request,
               user_action_time,
               client.bus_name,
               dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='EnsureChannel')
    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'] == client.bus_name
    assert request_props['Interfaces'] == []

    cr.Proceed(dbus_interface=cs.CR)

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

    assert add_request_call.args[0] == request_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'] == client.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)
    q.dbus_return(
        cm_request_call.message,
        True,  # <- Yours
        channel.object_path,
        channel.immutable,
        signature='boa{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
    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='')

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

    return channel
コード例 #31
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')

    # Empathy is an Observers who will crash
    empathy_bus = dbus.bus.BusConnection()
    empathy_bus.set_exit_on_disconnect(False)  # we'll disconnect later

    # Kopete is an Approver, Handler and will not crash
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    q.attach_to_bus(kopete_bus)

    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q,
                              empathy_bus,
                              'Empathy',
                              observe=[text_fixed_properties],
                              approve=[],
                              handle=[],
                              wants_recovery=True)
    kopete = SimulatedClient(q,
                             kopete_bus,
                             'Kopete',
                             observe=[],
                             approve=[text_fixed_properties],
                             handle=[text_fixed_properties],
                             bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # The Observer (Empathy) is told about the new channel

    e = q.expect('dbus-method-call',
                 path=empathy.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    # Empathy indicates that it is ready to proceed
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    # The Approver (Kopete) is next

    k = q.expect('dbus-method-call',
                 path=kopete.object_path,
                 interface=cs.APPROVER,
                 method='AddDispatchOperation',
                 handled=False)

    assert k.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]

    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # The user responds to Kopete
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Kopete')

    # Kopete is asked to handle the channels
    k = q.expect('dbus-method-call',
                 path=kopete.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)

    # Kopete accepts the channels
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWith'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Another channel: this one will remain unapproved

    channel2_properties = dbus.Dictionary(text_fixed_properties,
                                          signature='sv')
    channel2_properties[cs.CHANNEL + '.TargetID'] = 'mercutio'
    channel2_properties[cs.CHANNEL + '.TargetHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'mercutio')
    channel2_properties[cs.CHANNEL + '.InitiatorID'] = 'mercutio'
    channel2_properties[cs.CHANNEL + '.InitiatorHandle'] = \
            conn.ensure_handle(cs.HT_CONTACT, 'mercutio')
    channel2_properties[cs.CHANNEL + '.Requested'] = False
    channel2_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')

    chan2 = SimulatedChannel(conn, channel2_properties)
    chan2.announce()

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo2_path = e.args[0]
    cdo2_properties = e.args[1]

    assert cdo2_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo2_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo2_path, cdo2_properties)]

    cdo2 = bus.get_object(cs.CD, cdo2_path)
    cdo2_iface = dbus.Interface(cdo2, cs.CDO)
    cdo2_props_iface = dbus.Interface(cdo2, cs.PROPERTIES_IFACE)

    assert cdo2_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo2_properties[cs.CDO + '.Interfaces']
    assert cdo2_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo2_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo2_props_iface.Get(cs.CDO, 'Channels') == [(chan2.object_path,
                                                         channel2_properties)]
    assert cdo2_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo2_properties[cs.CDO + '.PossibleHandlers']

    # The Observer (Empathy) is told about the new channel

    e = q.expect('dbus-method-call',
                 path=empathy.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] == cdo2_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan2.object_path, channels
    assert channels[0][1] == channel2_properties, channels

    # Empathy indicates that it is ready to proceed
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    # The Approver (Kopete) is next; this time, we don't approve

    k = q.expect('dbus-method-call',
                 path=kopete.object_path,
                 interface=cs.APPROVER,
                 method='AddDispatchOperation',
                 handled=False)

    assert k.args == [[(chan2.object_path, channel2_properties)], cdo2_path,
                      cdo2_properties]

    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # 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] == ''),
    )
    empathy_unique_name = e.args[1]

    empathy_bus.flush()

    # Empathy gets restarted
    empathy.reacquire_name()

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

    e1, e2 = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     predicate=lambda e: e.args[2][0][0] == chan.object_path,
                     handled=False),
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     predicate=lambda e: e.args[2][0][0] == chan2.object_path,
                     handled=False),
    )

    assert e1.args[0] == account.object_path, e1.args
    assert e1.args[1] == conn.object_path, e1.args
    assert e1.args[4] == [], e1.args  # no requests satisfied
    assert e1.args[5]['recovering'] == 1, e1.args  # due to observer recovery
    channels = e1.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert e2.args[0] == account.object_path, e2.args
    assert e2.args[1] == conn.object_path, e2.args
    assert e2.args[4] == [], e2.args  # no requests satisfied
    assert e2.args[5]['recovering'] == 1, e2.args  # due to observer recovery
    channels = e2.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan2.object_path, channels
    assert channels[0][1] == channel2_properties, channels

    # Empathy indicates that it is ready to proceed
    q.dbus_return(e1.message, bus=empathy_bus, signature='')
    q.dbus_return(e2.message, bus=empathy_bus, signature='')

    sync_dbus(bus, q, mc)
コード例 #32
0
def test(q, bus, unused, **kwargs):
    fake_accounts_service = kwargs['fake_accounts_service']
    preseed(q, bus, fake_accounts_service)

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

    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', 'jc',
                               '*****@*****.**')
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, 0)

    unhandled_properties = dbus.Dictionary(text_fixed_properties,
                                           signature='sv')
    unhandled_properties[cs.CHANNEL +
                         '.Interfaces'] = dbus.Array(signature='s')
    unhandled_properties[cs.CHANNEL + '.TargetID'] = '*****@*****.**'
    unhandled_properties[cs.CHANNEL + '.TargetHandle'] = \
            dbus.UInt32(conn.ensure_handle(cs.HT_CONTACT, '*****@*****.**'))
    unhandled_properties[cs.CHANNEL + '.InitiatorHandle'] = dbus.UInt32(
        conn.self_handle)
    unhandled_properties[cs.CHANNEL + '.InitiatorID'] = conn.self_ident
    unhandled_properties[cs.CHANNEL + '.Requested'] = True
    unhandled_chan = SimulatedChannel(conn, unhandled_properties)
    unhandled_chan.announce()

    handled_properties = dbus.Dictionary(text_fixed_properties, signature='sv')
    handled_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')
    handled_properties[cs.CHANNEL + '.TargetID'] = '*****@*****.**'
    handled_properties[cs.CHANNEL + '.TargetHandle'] = \
            dbus.UInt32(conn.ensure_handle(cs.HT_CONTACT, '*****@*****.**'))
    handled_properties[cs.CHANNEL + '.InitiatorHandle'] = dbus.UInt32(
        conn.self_handle)
    handled_properties[cs.CHANNEL + '.InitiatorID'] = conn.self_ident
    handled_properties[cs.CHANNEL + '.Requested'] = True
    handled_chan = SimulatedChannel(conn, handled_properties)
    handled_chan.announce()

    client = SimulatedClient(q,
                             bus,
                             'Empathy',
                             observe=[text_fixed_properties],
                             approve=[text_fixed_properties],
                             handle=[text_fixed_properties],
                             bypass_approval=False)
    client.handled_channels.append(handled_chan.object_path)

    # Service-activate MC.
    # We're told about the other channel as an observer...
    mc = MC(q, bus, wait_for_names=False)
    e, = mc.wait_for_names(
        EventPattern('dbus-method-call',
                     path=client.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False), )

    assert e.args[1] == conn.object_path, e.args
    channels = e.args[2]
    assert channels[0][0] == unhandled_chan.object_path, channels
    q.dbus_return(e.message, signature='')

    # ... and as a handler
    e = q.expect('dbus-method-call',
                 path=client.object_path,
                 interface=cs.HANDLER,
                 method='HandleChannels',
                 handled=False)
    assert e.args[1] == conn.object_path, e.args
    channels = e.args[2]
    assert channels[0][0] == unhandled_chan.object_path, channels
    q.dbus_return(e.message, signature='')
コード例 #33
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)

    if prefer is None:
        prefer = client

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    # chat UI calls ChannelDispatcher.EnsureChannel or CreateChannel
    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 'EnsureChannel' or 'CreateChannel'),
               account.object_path,
               request,
               user_action_time,
               prefer.bus_name,
               dbus_interface=cs.CD)
    ret = q.expect('dbus-return',
                   method=(ensure and 'EnsureChannel' or 'CreateChannel'))
    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'] == []

    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

        # 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)
    assertContains('request-properties', e.args[5])
    assertContains(request_path, e.args[5]['request-properties'])
    assertLength(1, e.args[5]['request-properties'])
    assertEquals(request_props, e.args[5]['request-properties'][request_path])
    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()
    q.dbus_return(add_request_call.message, signature='')

    # Actually, never mind.
    cr.Cancel(dbus_interface=cs.CR)

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

    assert stdsig.args[0] == cs.CANCELLED
def test(q, bus, mc):
    params = dbus.Dictionary({"account": "*****@*****.**",
        "password": "******"}, signature='sv')
    simulated_cm, account = create_fakecm_account(q, bus, mc, params)

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

    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q, bus, 'Empathy',
            observe=[text_fixed_properties], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)
    kopete = SimulatedClient(q, bus, 'Kopete',
            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, [empathy, kopete])

    # Enable the account
    account.Set(cs.ACCOUNT, 'Enabled', True,
            dbus_interface=cs.PROPERTIES_IFACE)

    requested_presence = dbus.Struct((dbus.UInt32(2L),
        dbus.String(u'available'), dbus.String(u'')))
    account.Set(cs.ACCOUNT,
            'RequestedPresence', requested_presence,
            dbus_interface=cs.PROPERTIES_IFACE)

    e = q.expect('dbus-method-call', method='RequestConnection',
            args=['fakeprotocol', params],
            destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
            path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
            interface=cs.tp_name_prefix + '.ConnectionManager',
            handled=False)

    # Don't allow the Connection to have its list of channels
    # until we want it to, by avoiding a return from GetAll(Requests).
    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
            'myself', implement_get_channels=False)

    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    get_all_requests_call = q.expect('dbus-method-call',
            method='GetAll', args=[cs.CONN_IFACE_REQUESTS])

    q.expect('dbus-method-call', method='Connect',
            path=conn.object_path, handled=True)
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Before returning from GetAll(Requests), make a Channel spring into
    # existence

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

    # Now reply to GetAll(Requests)
    conn.GetAll_Requests(get_all_requests_call)

    # A channel dispatch operation is created for the channel we already had

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

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

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #36
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')

    # Logger is a text observer wanting recovery
    logger = SimulatedClient(q,
                             bus,
                             'LoggerChat',
                             observe=[text_fixed_properties],
                             bypass_approval=False,
                             wants_recovery=True)

    # 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, [logger, gs])

    cd = bus.get_object(cs.CD, cs.CD_PATH)

    # 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 and logger's observer are notified
    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=logger.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=gs.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    channels, cdo_path, props = k.args

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

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

    # gnome-shell claims the channel
    call_async(q, cdo_iface, 'Claim')
    e = q.expect('dbus-return', method='Claim')

    # Logger crash
    logger.release_name()

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

    bus.flush()

    # Logger gets restarted
    logger.reacquire_name()

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

    # Logger recovers the channel
    e = q.expect('dbus-method-call',
                 path=logger.object_path,
                 interface=cs.OBSERVER,
                 method='ObserveChannels',
                 handled=False)

    # gnome-shell which is handling the channel asks to re-ensure it
    cd_iface = dbus.Interface(cd, cs.CD)
    call_async(q, cd_iface, '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')

    chan.close()
コード例 #37
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')

    # Empathy is an observer for text channels with
    # DelayApprovers=TRUE.
    empathy = SimulatedClient(q, bus, 'Empathy',
        observe=[text_fixed_properties], approve=[],
        handle=[], delay_approvers=True)

    # Loggy is an observer for text channels with
    # DelayApprovers=FALSE.
    loggy = SimulatedClient(q, bus, 'Loggy',
        observe=[text_fixed_properties], approve=[],
        handle=[], delay_approvers=False)

    # Kopete is an approver and handler for text channels.
    kopete = SimulatedClient(q, bus, 'Kopete',
        observe=[], approve=[text_fixed_properties],
        handle=[text_fixed_properties])

    expect_client_setup(q, [empathy, loggy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # A text channel appears!
    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()

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    # Empathy, the observer, gets the channel to observe. Because it
    # has DelayApprovers=TRUE, Kopete should not have
    # AddDispatchOperation called on it until Empathy returns from
    # ObserveChannels. Because Loggy has DelayApprovers=False,
    # however, ADO can be called on Kopete before Loggy returns, but
    # again, only after Empathy returns.
    forbidden = [EventPattern('dbus-method-call',
            path=kopete.object_path,
            interface=cs.APPROVER, method='AddDispatchOperation')]
    q.forbid_events(forbidden)

    e, l = q.expect_many(EventPattern('dbus-method-call',
                 path=empathy.object_path,
                 interface=cs.OBSERVER, method='ObserveChannels',
                 handled=False),
             EventPattern('dbus-method-call',
                 path=loggy.object_path,
                 interface=cs.OBSERVER, method='ObserveChannels',
                 handled=False),
             )

    # Waste a little time here and there.  We can't call sync_dbus
    # here because it calls Ping and libdbus returns from Ping
    # synchronously and doesn't turn the main loop handle enough.
    call_async(q, cd_props, 'Get', cs.CD_IFACE_OP_LIST, 'DispatchOperations')
    event = q.expect('dbus-return', method='Get')

    # Finally return from ObserveChannels from Empathy, so now we
    # expect ADO to be called on Kopete.
    q.dbus_return(e.message, bus=bus, signature='')
    q.unforbid_events(forbidden)

    e = q.expect('dbus-method-call',
             path=kopete.object_path,
             interface=cs.APPROVER, method='AddDispatchOperation',
             handled=False)

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

    # Return from loggy's ObserveChannels.
    q.dbus_return(l.message, bus=bus, signature='')

    # The user responds to Kopete
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Kopete')

    # Kopete is asked to handle the channels
    k = q.expect('dbus-method-call',
            path=kopete.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    # Kopete accepts the channels
    q.dbus_return(k.message, bus=bus, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #38
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)

    # One client (Kopete) has less specific filters than the other (Empathy),
    # to make sure that the dispatcher would normally prefer Empathy; this
    # means that when we use Kopete as the preferred handler, we know that
    # if Kopete is invoked, then preferring the preferred handler correctly
    # took precedence over the normal logic.
    vague_fixed_properties = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        }, signature='sv')
    text_fixed_properties = dbus.Dictionary(
        {
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
        },
        signature='sv')

    empathy_bus = dbus.bus.BusConnection()
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    q.attach_to_bus(kopete_bus)
    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q,
                              empathy_bus,
                              'Empathy',
                              observe=[text_fixed_properties],
                              approve=[text_fixed_properties],
                              handle=[text_fixed_properties],
                              bypass_approval=False)
    kopete = SimulatedClient(q,
                             kopete_bus,
                             'Kopete',
                             observe=[vague_fixed_properties],
                             approve=[vague_fixed_properties],
                             handle=[vague_fixed_properties],
                             bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    # Empathy has a more specific filter, so it comes first
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
                                                        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention. However, the user is busy looking through the address
    # book, and independently decides to talk to Juliet. The address book
    # is from KDE so wants Kopete to be used.

    user_action_time = dbus.Int64(1238582606)

    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    call_async(q,
               cd,
               'EnsureChannel',
               account.object_path,
               request,
               user_action_time,
               kopete.bus_name,
               dbus_interface=cs.CD)
    ret, add_request_call = q.expect_many(
        EventPattern('dbus-return', method='EnsureChannel'),
        EventPattern('dbus-method-call',
                     handled=False,
                     interface=cs.CLIENT_IFACE_REQUESTS,
                     method='AddRequest',
                     path=kopete.object_path),
    )
    request_path = ret.value[0]

    assert add_request_call.args[0] == request_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'] == kopete.bus_name
    assert request_props[cs.CR + '.Interfaces'] == []

    # 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'] == kopete.bus_name
    assert request_props['Interfaces'] == []

    cr.Proceed(dbus_interface=cs.CR)

    cm_request_call = q.expect('dbus-method-call',
                               interface=cs.CONN_IFACE_REQUESTS,
                               method='EnsureChannel',
                               path=conn.object_path,
                               args=[request],
                               handled=False)

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

    # Time passes. The CM returns the existing channel

    q.dbus_return(cm_request_call.message,
                  False,
                  chan.object_path,
                  chan.immutable,
                  signature='boa{sv}')

    # EnsureChannel constitutes approval, so Kopete is told to handle the
    # channel

    e = q.expect('dbus-method-call',
                 path=kopete.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] == chan.object_path, channels
    assert channels[0][1] == chan.immutable, channels
    assert e.args[3] == [request_path], e.args
    assert e.args[4] == user_action_time, (e.args[4], user_action_time)
    assert isinstance(e.args[5], dict)
    assert len(e.args) == 6

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

    q.expect_many(
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
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.RespawnObservers'
        }, signature='sv')

    # Logger is an activatable Observer who will crash
    logger_bus = dbus.bus.BusConnection()
    logger_bus.set_exit_on_disconnect(False)   # we'll disconnect later

    # Kopete is an Approver, Handler and will not crash
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(logger_bus)
    q.attach_to_bus(kopete_bus)

    kopete = SimulatedClient(q, kopete_bus, 'Kopete',
            observe=[], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)

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

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    k = q.expect('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False)

    assert k.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]

    q.dbus_return(k.message, bus=kopete_bus, signature='')


    # The fake Logger implementation is run
    e = q.expect('dbus-signal',
            path=cs.tp_path_prefix + '/RegressionTests',
            interface=cs.tp_name_prefix + '.RegressionTests',
            signal='FakeStartup',
            args=[cs.tp_name_prefix + '.Client.Logger'],
            )
    # We take on its identity to be able to continue with the test
    logger = SimulatedClient(q, bus, 'Logger',
            observe=[text_fixed_properties])

    # Logger is told about the new channel
    e = q.expect('dbus-method-call',
                path=logger.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    # Logger indicates that it is ready to proceed
    q.dbus_return(e.message, bus=logger_bus, signature='')

    # The Approver (Kopete) is next

    # The user responds to Kopete
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Kopete')

    # Kopete is asked to handle the channels
    k = q.expect('dbus-method-call',
            path=kopete.object_path,
            interface=cs.HANDLER, method='HandleChannels',
            handled=False)

    # Kopete accepts the channels
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Logger crashes
    logger.release_name()

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

    logger_bus.flush()

    # Logger gets restart request
    e = q.expect('dbus-signal',
            path=cs.tp_path_prefix + '/RegressionTests',
            interface=cs.tp_name_prefix + '.RegressionTests',
            signal='FakeStartup',
            args=[cs.tp_name_prefix + '.Client.Logger'],
            )

    # Logger gets restarted
    logger.reacquire_name()

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

    e = q.expect('dbus-method-call',
                path=logger.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False)

    # FIXME: assert the same things as before, except CDO (which we don't
    # have) and account path (which we don't know how to get); also check
    # that the recovering observer info key is set
    assert e.args[0] == account.object_path, e.args
    assert e.args[1] == conn.object_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    assert e.args[5]['recovering'] == 1, e.args # due to observer recovery
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    # Logger indicates that it is ready to proceed
    q.dbus_return(e.message, bus=logger_bus, signature='')

    sync_dbus(bus, q, mc)
コード例 #40
0
def test(q, bus, mc):
    # Because the channels are handled by another process, we should never be
    # asked to approve or handle them.
    forbidden = [
        EventPattern('dbus-method-call', method='HandleChannels'),
        EventPattern('dbus-method-call', method='AddDispatchOperation'),
    ]
    q.forbid_events(forbidden)

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

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

    expect_client_setup(q, [empathy, kopete])

    # a non-MC-using client goes behind our back to call CreateChannel or
    # EnsureChannel on the Connection directly
    #
    # (This is not simulated here: we just behave as though it had happened)

    channel_immutable = dbus.Dictionary(text_fixed_properties)
    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_immutable[cs.CHANNEL + '.TargetID'] = 'juliet'
    channel = SimulatedChannel(conn, channel_immutable)

    channel.announce()

    # Observer should get told, processing waits for it
    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == [], 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 == k.args

    # Observers say "OK, go"
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    sync_dbus(bus, q, mc)
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')

    empathy_bus = dbus.bus.BusConnection()
    empathy_bus.set_exit_on_disconnect(False)   # we'll disconnect later
    kopete_bus = dbus.bus.BusConnection()
    q.attach_to_bus(empathy_bus)
    q.attach_to_bus(kopete_bus)
    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q, empathy_bus, 'Empathy',
            observe=[text_fixed_properties], approve=[text_fixed_properties],
            handle=[text_fixed_properties], bypass_approval=False)
    kopete = SimulatedClient(q, kopete_bus, 'Kopete',
            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, [empathy, kopete])

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # Using an invalid Handler name should fail
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.The.Moon.On.A.Stick')
    q.expect('dbus-error', method='HandleWith')
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.the moon on a stick')
    q.expect('dbus-error', method='HandleWith')

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
            cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWith'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)
    cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE)

    assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \
            cdo_properties[cs.CDO + '.Interfaces']
    assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path
    assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path,
        channel_properties)]
    assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \
            cdo_properties[cs.CDO + '.PossibleHandlers']

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=empathy_bus, signature='')
    q.dbus_return(e.message, bus=kopete_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWithTime',
            cs.tp_name_prefix + '.Client.Empathy', 13)

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

    account_path, conn_path, channels, requests, action_time, info = e.args
    assert action_time == 13

    # Empathy accepts the channels
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    q.expect_many(
            EventPattern('dbus-return', method='HandleWithTime'),
            EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
            EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
                signal='DispatchOperationFinished'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # From now on, it is an error to get HandleChannels (because we're
    # testing Claim())
    forbidden = [
            EventPattern('dbus-method-call', method='HandleChannels'),
            ]
    q.forbid_events(forbidden)

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

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

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
    assert cs.CDO + '.Interfaces' in cdo_properties

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
            cs.tp_name_prefix + '.Client.Kopete'], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args      # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == claimed_chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, bus=kopete_bus, signature='')
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    # The Approvers are next

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    assert e.args == [[(claimed_chan.object_path, channel_properties)],
            cdo_path, cdo_properties]
    assert k.args == e.args

    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first, and Empathy decides it wants the
    # channel for itself
    empathy_cdo = empathy_bus.get_object(cdo.bus_name, cdo.object_path)
    empathy_cdo_iface = dbus.Interface(empathy_cdo, cs.CDO)
    call_async(q, empathy_cdo_iface, 'Claim')

    q.expect_many(
            EventPattern('dbus-signal', path=cdo_path, signal='Finished'),
            EventPattern('dbus-signal', path=cs.CD_PATH,
                signal='DispatchOperationFinished', args=[cdo_path]),
            EventPattern('dbus-return', method='Claim'),
            )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

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

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

    # third_chan should not be closed
    q.unforbid_events(forbidden)
    forbidden.append(EventPattern('dbus-method-call', method='Close',
        path=third_chan.object_path))
    q.forbid_events(forbidden)

    # A channel dispatch operation is created

    e = q.expect('dbus-signal',
            path=cs.CD_PATH,
            interface=cs.CD_IFACE_OP_LIST,
            signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            )
    q.dbus_return(k.message, bus=kopete_bus, signature='')
    q.dbus_return(e.message, bus=empathy_bus, signature='')

    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=empathy.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            EventPattern('dbus-method-call',
                path=kopete.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )
    q.dbus_return(e.message, bus=empathy_bus, signature='')
    q.dbus_return(k.message, bus=kopete_bus, signature='')

    # Kopete closes this one
    kopete_cdo = kopete_bus.get_object(cdo.bus_name, cdo.object_path)
    kopete_cdo_iface = dbus.Interface(kopete_cdo, cs.CDO)
    call_async(q, kopete_cdo_iface, 'Claim')

    q.expect_many(
            EventPattern('dbus-signal', path=cdo_path, signal='Finished'),
            EventPattern('dbus-signal', path=cs.CD_PATH,
                signal='DispatchOperationFinished', args=[cdo_path]),
            EventPattern('dbus-return', method='Claim'),
            )

    # 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] == ''),
            )
    empathy_unique_name = e.args[1]

    empathy_bus.flush()
    empathy_bus.close()

    # In response, the channels that were being handled by Empathy are closed.
    # Kopete's channel is *not* closed.
    q.expect_many(
            EventPattern('dbus-signal',
                signal='NameOwnerChanged',
                predicate=(lambda e:
                    e.args[0] == empathy_unique_name and e.args[2] == '')),
            EventPattern('dbus-method-call',
                path=chan.object_path, method='Close'),
            EventPattern('dbus-method-call',
                path=claimed_chan.object_path, method='Close'),
            )

    sync_dbus(bus, q, mc)
    q.unforbid_events(forbidden)
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')

    # Logger is a text observer wanting recovery
    logger = SimulatedClient(q, bus, 'LoggerChat',
            observe=[text_fixed_properties],
            bypass_approval=False,
            wants_recovery=True)

    # 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, [logger, gs])

    cd = bus.get_object(cs.CD, cs.CD_PATH)

    # 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 and logger's observer are notified
    e, k = q.expect_many(
            EventPattern('dbus-method-call',
                path=logger.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False),
            EventPattern('dbus-method-call',
                path=gs.object_path,
                interface=cs.APPROVER, method='AddDispatchOperation',
                handled=False),
            )

    channels, cdo_path, props = k.args

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

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

    # gnome-shell claims the channel
    call_async(q, cdo_iface, 'Claim')
    e = q.expect('dbus-return', method='Claim')

    # Logger crash
    logger.release_name()

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

    bus.flush()

    # Logger gets restarted
    logger.reacquire_name()

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

    # Logger recovers the channel
    e = q.expect('dbus-method-call',
                path=logger.object_path,
                interface=cs.OBSERVER, method='ObserveChannels',
                handled=False)

    # gnome-shell which is handling the channel asks to re-ensure it
    cd_iface = dbus.Interface(cd, cs.CD)
    call_async(q, cd_iface, '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')

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

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

    # Two clients want to observe, approve and handle channels
    empathy = SimulatedClient(q,
                              bus,
                              'Empathy',
                              observe=[text_fixed_properties],
                              approve=[text_fixed_properties],
                              handle=[text_fixed_properties],
                              bypass_approval=False)
    kopete = SimulatedClient(q,
                             bus,
                             'Kopete',
                             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, [empathy, kopete])

    # Enable the account
    account.Set(cs.ACCOUNT,
                'Enabled',
                True,
                dbus_interface=cs.PROPERTIES_IFACE)

    requested_presence = dbus.Struct(
        (dbus.UInt32(2L), dbus.String(u'available'), dbus.String(u'')))
    account.Set(cs.ACCOUNT,
                'RequestedPresence',
                requested_presence,
                dbus_interface=cs.PROPERTIES_IFACE)

    e = q.expect('dbus-method-call',
                 method='RequestConnection',
                 args=['fakeprotocol', params],
                 destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
                 path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
                 interface=cs.tp_name_prefix + '.ConnectionManager',
                 handled=False)

    # Don't allow the Connection to have its list of channels
    # until we want it to, by avoiding a return from GetAll(Requests).
    conn = SimulatedConnection(q,
                               bus,
                               'fakecm',
                               'fakeprotocol',
                               '_',
                               'myself',
                               implement_get_channels=False)

    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    get_all_requests_call = q.expect('dbus-method-call',
                                     method='GetAll',
                                     args=[cs.CONN_IFACE_REQUESTS])

    q.expect('dbus-method-call',
             method='Connect',
             path=conn.object_path,
             handled=True)
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)

    # subscribe to the OperationList interface (MC assumes that until this
    # property has been retrieved once, nobody cares)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []

    # Before returning from GetAll(Requests), make a Channel spring into
    # existence

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

    # Now reply to GetAll(Requests)
    conn.GetAll_Requests(get_all_requests_call)

    # A channel dispatch operation is created for the channel we already had

    e = q.expect('dbus-signal',
                 path=cs.CD_PATH,
                 interface=cs.CD_IFACE_OP_LIST,
                 signal='NewDispatchOperation')

    cdo_path = e.args[0]
    cdo_properties = e.args[1]

    assert cdo_properties[cs.CDO + '.Account'] == account.object_path
    assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path

    handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
    handlers.sort()
    assert handlers == [
        cs.tp_name_prefix + '.Client.Empathy',
        cs.tp_name_prefix + '.Client.Kopete'
    ], handlers

    assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
            [(cdo_path, cdo_properties)]

    cdo = bus.get_object(cs.CD, cdo_path)
    cdo_iface = dbus.Interface(cdo, cs.CDO)

    # Both Observers are told about the new channel

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.OBSERVER,
                     method='ObserveChannels',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.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] == cdo_path, e.args
    assert e.args[4] == [], e.args  # no requests satisfied
    channels = e.args[2]
    assert len(channels) == 1, channels
    assert channels[0][0] == chan.object_path, channels
    assert channels[0][1] == channel_properties, channels

    assert k.args == e.args

    # Both Observers indicate that they are ready to proceed
    q.dbus_return(k.message, signature='')
    q.dbus_return(e.message, signature='')

    # The Approvers are next

    e, k = q.expect_many(
        EventPattern('dbus-method-call',
                     path=empathy.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
        EventPattern('dbus-method-call',
                     path=kopete.object_path,
                     interface=cs.APPROVER,
                     method='AddDispatchOperation',
                     handled=False),
    )

    assert e.args == [[(chan.object_path, channel_properties)], cdo_path,
                      cdo_properties]
    assert k.args == e.args

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

    # Both Approvers now have a flashing icon or something, trying to get the
    # user's attention

    # The user responds to Empathy first
    call_async(q, cdo_iface, 'HandleWith',
               cs.tp_name_prefix + '.Client.Empathy')

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

    # Empathy accepts the channels
    q.dbus_return(e.message, signature='')

    q.expect_many(
        EventPattern('dbus-return', method='HandleWith'),
        EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
        EventPattern('dbus-signal',
                     interface=cs.CD_IFACE_OP_LIST,
                     signal='DispatchOperationFinished'),
    )

    # Now there are no more active channel dispatch operations
    assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
コード例 #44
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),
    )
コード例 #45
0
def test(q, bus, mc):
    params = dbus.Dictionary(
        {
            "account": "*****@*****.**",
            "password": "******"
        }, signature='sv')
    (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)

    account_iface = dbus.Interface(account, cs.ACCOUNT)
    account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)

    # Ensure that it's enabled but has offline RP and doesn't connect
    # automatically

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
               (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
    q.expect('dbus-return', method='Set')

    call_async(
        q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence',
        (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Testing automatic presence'))
    q.expect('dbus-return', method='Set')
    q.expect(
        'dbus-signal',
        signal='AccountPropertyChanged',
        predicate=lambda e: e.args[0].get('AutomaticPresence',
                                          (None, None, None))[1] == 'busy')

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'ConnectAutomatically',
               False)
    q.expect('dbus-return', method='Set')

    call_async(q, account_props, 'Set', cs.ACCOUNT, 'Enabled', True)
    q.expect('dbus-return', method='Set')
    q.expect('dbus-signal',
             signal='AccountPropertyChanged',
             predicate=lambda e: e.args[0].get('Enabled'))

    # Requesting a channel will put us online

    user_action_time = dbus.Int64(1238582606)

    cd = bus.get_object(cs.CD, cs.CD_PATH)

    request = dbus.Dictionary(
        {
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
        },
        signature='sv')
    call_async(q,
               cd,
               'CreateChannel',
               account.object_path,
               request,
               user_action_time,
               "",
               dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='CreateChannel')
    request_path = ret.value[0]

    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'] == ""
    assert request_props['Interfaces'] == []

    # make sure RequestConnection doesn't get called until we Proceed
    events = [EventPattern('dbus-method-call', method='RequestConnection')]
    q.forbid_events(events)

    sync_dbus(bus, q, mc)

    q.unforbid_events(events)

    cr.Proceed(dbus_interface=cs.CR)

    e = q.expect('dbus-method-call',
                 method='RequestConnection',
                 args=['fakeprotocol', params],
                 destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
                 path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
                 interface=cs.tp_name_prefix + '.ConnectionManager',
                 handled=False)

    conn = SimulatedConnection(q,
                               bus,
                               'fakecm',
                               'fakeprotocol',
                               '_',
                               'myself',
                               has_presence=True)

    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')

    q.expect('dbus-method-call',
             method='Connect',
             path=conn.object_path,
             handled=True)
    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
    conn.presence = dbus.Struct((cs.PRESENCE_AVAILABLE, 'available', ''),
                                signature='uss')

    _, cm_request_call = q.expect_many(
        EventPattern('dbus-method-call',
                     path=conn.object_path,
                     interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
                     method='SetPresence',
                     args=['busy', 'Testing automatic presence'],
                     handled=True),
        EventPattern('dbus-method-call',
                     path=conn.object_path,
                     interface=cs.CONN_IFACE_REQUESTS,
                     method='CreateChannel',
                     args=[request],
                     handled=False),
    )

    q.dbus_emit(conn.object_path,
                cs.CONN_IFACE_SIMPLE_PRESENCE,
                'PresencesChanged', {
                    conn.self_handle: (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
                                       'Testing automatic presence')
                },
                signature='a{u(uss)}')

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

    # there's no handler, so it gets shot down

    q.expect('dbus-method-call',
             path=channel.object_path,
             method='Close',
             handled=True)
def test_channel_creation(q, bus, account, client, conn,
        yours_first=True, swap_requests=False):
    user_action_time1 = dbus.Int64(1238582606)
    user_action_time2 = dbus.Int64(1244444444)

    cd = bus.get_object(cs.CD, cs.CD_PATH)
    cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)

    # chat UI calls ChannelDispatcher.EnsureChannel
    request = dbus.Dictionary({
            cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
            cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
            cs.CHANNEL + '.TargetID': 'juliet',
            }, signature='sv')
    call_async(q, cd, 'EnsureChannel',
            account.object_path, request, user_action_time1, client.bus_name,
            dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='EnsureChannel')
    request_path = ret.value[0]

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

    cr1 = bus.get_object(cs.AM, request_path)
    request_props = cr1.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_time1
    assert request_props['PreferredHandler'] == client.bus_name
    assert request_props['Interfaces'] == []

    cr1.Proceed(dbus_interface=cs.CR)

    cm_request_call1, add_request_call1 = q.expect_many(
            EventPattern('dbus-method-call',
                interface=cs.CONN_IFACE_REQUESTS,
                method='EnsureChannel',
                path=conn.object_path, args=[request], handled=False),
            EventPattern('dbus-method-call', handled=False,
                interface=cs.CLIENT_IFACE_REQUESTS,
                method='AddRequest', path=client.object_path),
            )

    # Before the first request has succeeded, the user gets impatient and
    # the UI re-requests.
    call_async(q, cd, 'EnsureChannel',
            account.object_path, request, user_action_time2, client.bus_name,
            dbus_interface=cs.CD)
    ret = q.expect('dbus-return', method='EnsureChannel')
    request_path = ret.value[0]
    cr2 = bus.get_object(cs.AM, request_path)

    request_props = cr2.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_time2
    assert request_props['PreferredHandler'] == client.bus_name
    assert request_props['Interfaces'] == []

    cr2.Proceed(dbus_interface=cs.CR)

    cm_request_call2, add_request_call2 = q.expect_many(
            EventPattern('dbus-method-call',
                interface=cs.CONN_IFACE_REQUESTS,
                method='EnsureChannel',
                path=conn.object_path, args=[request], handled=False),
            EventPattern('dbus-method-call', handled=False,
                interface=cs.CLIENT_IFACE_REQUESTS,
                method='AddRequest', path=client.object_path),
            )

    assert add_request_call1.args[0] == cr1.object_path
    request_props1 = add_request_call1.args[1]
    assert request_props1[cs.CR + '.Account'] == account.object_path
    assert request_props1[cs.CR + '.Requests'] == [request]
    assert request_props1[cs.CR + '.UserActionTime'] == user_action_time1
    assert request_props1[cs.CR + '.PreferredHandler'] == client.bus_name
    assert request_props1[cs.CR + '.Interfaces'] == []

    assert add_request_call2.args[0] == cr2.object_path
    request_props2 = add_request_call2.args[1]
    assert request_props2[cs.CR + '.Account'] == account.object_path
    assert request_props2[cs.CR + '.Requests'] == [request]
    assert request_props2[cs.CR + '.UserActionTime'] == user_action_time2
    assert request_props2[cs.CR + '.PreferredHandler'] == client.bus_name
    assert request_props2[cs.CR + '.Interfaces'] == []

    q.dbus_return(add_request_call1.message, signature='')
    q.dbus_return(add_request_call2.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)

    # Having announce() (i.e. NewChannels) come last is guaranteed by
    # telepathy-spec (since 0.17.14). There is no other ordering guarantee.

    if swap_requests:
        m2, m1 = cm_request_call1.message, cm_request_call2.message
    else:
        m1, m2 = cm_request_call1.message, cm_request_call2.message

    q.dbus_return(m1, yours_first,
            channel.object_path, channel.immutable, signature='boa{sv}')
    q.dbus_return(m2, not yours_first,
            channel.object_path, channel.immutable, signature='boa{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 sorted(e.args[4]) == sorted([cr1.object_path,
        cr2.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

    # 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 sorted(e.args[3]) == sorted([cr1.object_path,
        cr2.object_path]), e.args
    assert e.args[4] == user_action_time2, (e.args[4], user_action_time2)
    assert isinstance(e.args[5], dict)
    assertContains('request-properties', e.args[5])
    assertContains(cr1.object_path, e.args[5]['request-properties'])
    assertContains(cr2.object_path, e.args[5]['request-properties'])
    assertLength(2, e.args[5]['request-properties'])
    assertEquals(request_props1,
            e.args[5]['request-properties'][cr1.object_path])
    assertEquals(request_props2,
            e.args[5]['request-properties'][cr2.object_path])
    assert len(e.args) == 6

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

    return channel