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) # This client doesn't say it can handle channels, but if it requests one # for itself, we'll at least try dispatching to it. # # A real-world use case for this is if a client wants to request channels, # and handle the channels that it, itself, requested, but not handle # anything requested by others: for instance, nautilus-sendto behaves # like this. See fd.o #23651 unsuitable = SimulatedClient(q, bus, 'Unsuitable', observe=[], approve=[], handle=[], is_handler=True, 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, unsuitable]) test_channel_creation(q, bus, account, client, conn, False) test_channel_creation(q, bus, account, client, conn, True) test_channel_creation(q, bus, account, client, conn, False, unsuitable) test_channel_creation(q, bus, account, client, conn, False, unsuitable, cs.CHANNEL_TYPE_CALL)
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], handle=[text_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [client]) test_channel_creation(q, bus, account, client, conn, False) test_channel_creation(q, bus, account, client, conn, True)
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]) test_channel_creation(q, bus, account, client, conn, False) test_channel_creation(q, bus, account, client, conn, True)
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') # Emulate a handler that only wants to get outgoing channels, as a # regression test for <http://bugs.freedesktop.org/show_bug.cgi?id=23935>, # in which those didn't work text_requested = dbus.Dictionary(text_fixed_properties, signature='sv') text_requested[cs.CHANNEL + '.Requested'] = True client = SimulatedClient(q, bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_requested], 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]) test_channel_creation(q, bus, account, client, conn, False) test_channel_creation(q, bus, account, client, conn, True)
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) policy_bus_name_ref = dbus.service.BusName('com.example.Policy', bus) # For the beginning of this test, we should never be asked to handle # a channel. forbidden = [ 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') == [] e, chan, cdo_path = signal_channel_expect_query(q, bus, account, conn, empathy, kopete) # No. q.dbus_raise(e.message, 'com.example.Errors.No', 'Denied!') # The plugin responds _, _, 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() # Try again e, chan, cdo_path = signal_channel_expect_query(q, bus, account, conn, empathy, kopete) # Yes. q.dbus_return(e.message, 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, signature='') q.dbus_return(k.message, signature='') empathy_cdo = bus.get_object(cs.CD, cdo_path) empathy_cdo_iface = dbus.Interface(empathy_cdo, cs.CDO) call_async(q, empathy_cdo_iface, 'Claim') check_handler = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='CheckHandler') q.dbus_raise(check_handler.message, 'com.example.Errors.No', "That handler doesn't have enough options") q.expect('dbus-error', method='Claim', name=cs.PERMISSION_DENIED) kopete_cdo = bus.get_object(cs.CD, cdo_path) kopete_cdo_iface = dbus.Interface(kopete_cdo, cs.CDO) call_async(q, kopete_cdo_iface, 'Claim') check_handler = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='CheckHandler') q.dbus_return(check_handler.message, signature='') 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'), ) sync_dbus(bus, q, mc) # Try again; this time we'll reject a selected handler e, chan, cdo_path = signal_channel_expect_query(q, bus, account, conn, empathy, kopete) # The request is fine, continue... q.dbus_return(e.message, 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, signature='') q.dbus_return(k.message, signature='') kopete_cdo = bus.get_object(cs.CD, cdo_path) kopete_cdo_iface = dbus.Interface(kopete_cdo, cs.CDO) call_async(q, kopete_cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Kopete') check_handler = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='CheckHandler') q.dbus_raise(check_handler.message, 'com.example.Errors.No', 'That handler is not good enough') q.expect('dbus-error', method='HandleWith', name=cs.PERMISSION_DENIED) # well, let's try *something*... Kopete has been marked as failed, # so this will try Empathy call_async(q, kopete_cdo_iface, 'HandleWith', '') check_handler = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='CheckHandler') q.dbus_raise(check_handler.message, 'com.example.Errors.No', 'That handler is no good either') # Oops... we ran out of handlers _, _, _, e = q.expect_many( EventPattern('dbus-error', method='HandleWith', name=cs.PERMISSION_DENIED), 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() sync_dbus(bus, q, mc) # From now on we no longer want to forbid HandleChannels, but we do want # to forbid AddDispatchOperation q.unforbid_events(forbidden) forbidden = [ EventPattern('dbus-method-call', method='AddDispatchOperation'), ] q.forbid_events(forbidden) # Try yet again policy_request, chan, cdo_path = signal_channel_expect_query(q, bus, account, conn, empathy, kopete) # Before the policy service replies, someone requests the same channel user_action_time = dbus.Int64(1238582606) call_async(q, cd, 'EnsureChannel', account.object_path, chan.immutable, 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] cr = bus.get_object(cs.CD, request_path) 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=[chan.immutable], handled=False) q.dbus_return(add_request_call.message, signature='') # Time passes. The CM returns the existing channel, and the policy # service gets round to replying q.dbus_return(cm_request_call.message, False, chan.object_path, chan.immutable, signature='boa{sv}') q.dbus_return(policy_request.message, signature='') # Now we want to pass the channel to the selected handler. # What does the policy service think about that? check_handler = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='CheckHandler') # Yeah, we're OK with that. q.dbus_return(check_handler.message, signature='') 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 # Handler accepts the Channels q.dbus_return(e.message, signature='') q.expect_many( EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) 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 + '.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') == []
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') == []
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)
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') == []
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)
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)
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()
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 + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') # We have more than one Client "head" on the same unique name, to test # fd.o #24645 - we want the same "head" to be reinvoked if at all possible # This one is first in alphabetical order, is discovered first, and can # handle all channels, but is not the one we want empathy_worse_match = SimulatedClient(q, bus, 'A.Temporary.Handler', observe=[], approve=[], handle=[[]], bypass_approval=False) # This is the one we actually want empathy = SimulatedClient(q, bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) # this one is a closer match, but not the preferred handler closer_match = dbus.Dictionary(text_fixed_properties) closer_match[cs.CHANNEL + '.TargetID'] = 'juliet' empathy_better_match = SimulatedClient(q, bus, 'Empathy.BetterMatch', observe=[], approve=[], handle=[closer_match], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy_worse_match, empathy, empathy_better_match]) channel = test_channel_creation(q, bus, account, empathy, conn) # After the channel has been dispatched, a handler that would normally # be a closer match turns up. Regardless, we should not redispatch to it. # For the better client to be treated as if it's in a different process, # it needs its own D-Bus connection. closer_match = dbus.Dictionary(text_fixed_properties) closer_match[cs.CHANNEL + '.TargetID'] = 'juliet' closer_match[cs.CHANNEL + '.InitiatorID'] = conn.self_ident better_bus = dbus.bus.BusConnection() q.attach_to_bus(better_bus) better = SimulatedClient(q, better_bus, 'BetterMatch', observe=[], approve=[], handle=[closer_match], bypass_approval=False) expect_client_setup(q, [better]) test_channel_redispatch(q, bus, account, empathy, conn, channel) test_channel_redispatch(q, bus, account, empathy, conn, channel, ungrateful_handler=True) empathy.release_name() empathy_better_match.release_name() empathy_worse_match.release_name() test_channel_redispatch(q, bus, account, empathy, conn, channel, client_gone=True) channel.close()
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='')
def test(q, bus, mc): # Two clients want to handle channels: MediaCall is running, and AbiWord # is activatable. # this must match the .client file abi_contact_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAM_TUBE, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL_TYPE_STREAM_TUBE + '.Service': 'x-abiword', }, signature='sv') abi_room_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAM_TUBE, cs.CHANNEL + '.TargetHandleType': cs.HT_ROOM, cs.CHANNEL_TYPE_STREAM_TUBE + '.Service': 'x-abiword', }, signature='sv') media_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL, }, signature='sv') media_call = SimulatedClient(q, bus, 'MediaCall', observe=[], approve=[], handle=[media_fixed_properties], cap_tokens=[cs.CHANNEL_TYPE_CALL + '/ice', cs.CHANNEL_TYPE_CALL + '/audio/speex', cs.CHANNEL_TYPE_CALL + '/video/theora'], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [media_call]) def check_contact_caps(e): structs = e.args[0] filters = {} tokens = {} assert len(structs) == 3 for struct in structs: assert struct[0] not in filters filters[struct[0]] = sorted(struct[1]) tokens[struct[0]] = sorted(struct[2]) assert media_fixed_properties in filters[cs.CLIENT + '.MediaCall'] assert len(filters[cs.CLIENT + '.MediaCall']) == 1 assert abi_room_fixed_properties in filters[cs.CLIENT + '.AbiWord'] assert abi_contact_fixed_properties in filters[cs.CLIENT + '.AbiWord'] assert len(filters[cs.CLIENT + '.AbiWord']) == 2 assert len(tokens[cs.CLIENT + '.MediaCall']) == 3 assert cs.CHANNEL_TYPE_CALL + '/ice' in \ tokens[cs.CLIENT + '.MediaCall'] assert cs.CHANNEL_TYPE_CALL + '/audio/speex' in \ tokens[cs.CLIENT + '.MediaCall'] assert cs.CHANNEL_TYPE_CALL + '/video/theora' in \ tokens[cs.CLIENT + '.MediaCall'] assert len(tokens[cs.CLIENT + '.AbiWord']) == 2 assert 'com.example.Foo' in tokens[cs.CLIENT + '.AbiWord'] assert 'com.example.Bar' in tokens[cs.CLIENT + '.AbiWord'] return True params = dbus.Dictionary({"account": "*****@*****.**", "password": "******"}, signature='sv') simulated_cm, account = create_fakecm_account(q, bus, mc, params) conn, before = enable_fakecm_account(q, bus, mc, account, params, extra_interfaces=[cs.CONN_IFACE_CONTACT_CAPS], expect_before_connect=[ EventPattern('dbus-method-call', handled=False, interface=cs.CONN_IFACE_CONTACT_CAPS, method='UpdateCapabilities', predicate=check_contact_caps), ]) q.dbus_return(before.message, signature='') irssi_bus = dbus.bus.BusConnection() irssi_bus.set_exit_on_disconnect(False) # we'll disconnect later q.attach_to_bus(irssi_bus) irssi_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_ROOM, }, signature='sv') irssi = SimulatedClient(q, irssi_bus, 'Irssi', observe=[], approve=[], handle=[irssi_fixed_properties], cap_tokens=[], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [irssi]) e = q.expect('dbus-method-call', handled=False, interface=cs.CONN_IFACE_CONTACT_CAPS, method='UpdateCapabilities') assert len(e.args[0]) == 1 struct = e.args[0][0] assert struct[0] == cs.CLIENT + '.Irssi' assert struct[1] == [irssi_fixed_properties] assert struct[2] == [] # When Irssi exits, the CM is told it has gone irssi.release_name() del irssi irssi_bus.flush() irssi_bus.close() e = q.expect('dbus-method-call', handled=False, interface=cs.CONN_IFACE_CONTACT_CAPS, method='UpdateCapabilities') assert len(e.args[0]) == 1 struct = e.args[0][0] assert struct[0] == cs.CLIENT + '.Irssi' assert struct[1] == [] assert struct[2] == []
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') # 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 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()
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') == []
def test(q, bus, mc): params = dbus.Dictionary( { "account": "*****@*****.**", "password": "******" }, signature='sv') simulated_cm, account = create_fakecm_account(q, bus, mc, params) conn = enable_fakecm_account(q, bus, mc, account, params) text_fixed_properties = dbus.Dictionary( { cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') client = SimulatedClient(q, bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [client]) 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, 'CreateChannel', account.object_path, request, dbus.Int64(1234), 'grr.arg', # a valid bus name, but the wrong prefix dbus_interface=cs.CD) ret = q.expect('dbus-error', method='CreateChannel') assert ret.error.get_dbus_name() == cs.INVALID_ARGUMENT call_async( q, cd, 'CreateChannel', account.object_path, request, dbus.Int64(1234), 'can has cheeseburger?', # a totally invalid bus name dbus_interface=cs.CD) ret = q.expect('dbus-error', method='CreateChannel') assert ret.error.get_dbus_name() == cs.INVALID_ARGUMENT
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) # 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) # Two clients want to observe, approve and handle channels. Additionally, # Kopete recognises an "Urgent" flag on certain incoming channels, and # wants to bypass approval for them. 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=[contact_text_fixed_properties], approve=[contact_text_fixed_properties], handle=[contact_text_fixed_properties], bypass_approval=False) bypass = SimulatedClient(q, bus, 'Kopete.BypassApproval', observe=[], approve=[], handle=[urgent_fixed_properties], bypass_approval=True) # wait for MC to download the properties expect_client_setup(q, [empathy, kopete, bypass]) # 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 non-urgent channel is created cdo_iface, chan, channel_properties, observe_events = announce_common( q, bus, empathy, kopete, account, conn, cd_props, False) # Both Observers indicate that they are ready to proceed for e in observe_events: q.dbus_return(e.message, signature='') expect_and_exercise_approval(q, bus, chan, channel_properties, empathy, kopete, cdo_iface, cd_props) # Now a channel that bypasses approval comes in. During this process, # we should never be asked to approve anything. approval = [ EventPattern('dbus-method-call', method='AddDispatchOperation'), ] q.forbid_events(approval) cdo_iface, chan, channel_properties, observe_events = announce_common( q, bus, empathy, kopete, account, conn, cd_props, True) # Both Observers indicate that they are ready to proceed for e in observe_events: q.dbus_return(e.message, signature='') # Kopete'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) # Kopete accepts the channels q.dbus_return(e.message, signature='') q.unforbid_events(approval) # Regression test for fd.o #22670 closure = [ EventPattern('dbus-method-call', method='Close'), ] q.forbid_events(closure) bypass.release_name() sync_dbus(bus, q, mc) q.unforbid_events(closure) # Bring back that handler del bypass bypass = SimulatedClient(q, bus, 'Kopete.BypassApproval', observe=[], approve=[], handle=[urgent_fixed_properties], bypass_approval=True) expect_client_setup(q, [bypass]) # Another channel that bypasses approval comes in, but the handler that # bypasses approval fails. cdo_iface, chan, channel_properties, observe_events = announce_common( q, bus, empathy, kopete, account, conn, cd_props, True) # Both Observers indicate that they are ready to proceed for e in observe_events: q.dbus_return(e.message, signature='') # Kopete'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) # Kopete's BypassApproval part fails to accept the channels q.dbus_raise(e.message, 'com.example.Broken', 'No way') # MC recovers by running the approvers and doing what they say expect_and_exercise_approval(q, bus, chan, channel_properties, empathy, kopete, cdo_iface, cd_props)
def test(q, bus, mc): policy_bus_name_ref = dbus.service.BusName('com.example.Policy', bus) params = dbus.Dictionary( { "account": "*****@*****.**", "password": "******" }, signature='sv') simulated_cm, account = create_fakecm_account(q, bus, mc, params) conn, e = enable_fakecm_account( q, bus, mc, account, params, extra_interfaces=[cs.CONN_IFACE_SERVICE_POINT], expect_after_connect=[ EventPattern( 'dbus-method-call', method='Get', args=[cs.CONN_IFACE_SERVICE_POINT, 'KnownServicePoints']), ]) e_numbers = ['911', '112'] points = dbus.Array( [((cs.SERVICE_POINT_TYPE_EMERGENCY, 'urn:service:sos'), e_numbers)], signature='((us)as)') q.dbus_return(e.message, points, signature='v') # the service points change e_numbers = ['911', '112', '999'] points = dbus.Array( [((cs.SERVICE_POINT_TYPE_EMERGENCY, 'urn:service:sos'), e_numbers)], signature='((us)as)') q.dbus_emit(conn.object_path, cs.CONN_IFACE_SERVICE_POINT, 'ServicePointsChanged', points, signature='a((us)as)') # MC used to critical if more than one emergency service point was # given by the CM. That's silly, so let's test it. e_numbers1 = ['911'] e_numbers2 = ['999'] points = dbus.Array( [((cs.SERVICE_POINT_TYPE_EMERGENCY, 'urn:service:sos'), e_numbers1), ((cs.SERVICE_POINT_TYPE_EMERGENCY, 'urn:service:sos'), e_numbers2)], signature='((us)as)') q.dbus_emit(conn.object_path, cs.CONN_IFACE_SERVICE_POINT, 'ServicePointsChanged', points, signature='a((us)as)') e_numbers = e_numbers1 + e_numbers2 fixed_properties = dbus.Dictionary( { cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': DELAYED_CTYPE, }, signature='sv') client = SimulatedClient(q, bus, 'Empathy', observe=[fixed_properties], approve=[fixed_properties], handle=[fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [client]) user_action_time = dbus.Int64(1238582606) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) for emergency in False, True: if emergency: target_id = '112' forbidden = [ EventPattern('dbus-method-call', method='RequestRequest'), ] else: target_id = 'juliet' # For now, we should never actually be asked to make a channel. forbidden = [ EventPattern('dbus-method-call', method='CreateChannel'), EventPattern('dbus-method-call', method='EnsureChannel'), EventPattern('dbus-method-call', method='ObserveChannels'), EventPattern('dbus-method-call', method='AddDispatchOperation'), EventPattern('dbus-method-call', method='HandleChannels'), ] q.forbid_events(forbidden) # UI calls ChannelDispatcher.CreateChannel request = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': DELAYED_CTYPE, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': target_id, }, 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] # 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'] == [] call_async(q, cr, 'Proceed', dbus_interface=cs.CR) q.expect('dbus-return', method='Proceed') if emergency: # The CM is asked to create the channel anyway, because this # looks a bit like an emergency call cm_request_call = q.expect('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel', path=conn.object_path, args=[request], handled=False) q.dbus_raise(cm_request_call.message, cs.INVALID_ARGUMENT, 'No') sync_dbus(bus, q, account) q.unforbid_events(forbidden) else: # What does the policy service think? permission = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='RequestRequest') # Think about it for a bit, then allow dispatching to continue sync_dbus(bus, q, account) q.unforbid_events(forbidden) q.dbus_return(permission.message, signature='') # Only now does the CM's CreateChannel method get called cm_request_call = q.expect('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel', path=conn.object_path, args=[request], handled=False) q.dbus_raise(cm_request_call.message, cs.INVALID_ARGUMENT, 'No')
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() 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') == []
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), )
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') == []
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)