def signal_channel_expect_query(q, bus, account, conn, empathy, kopete): # This target is special-cased in test-plugin.c target = '*****@*****.**' channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = target channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, target) channel_properties[cs.CHANNEL + '.InitiatorID'] = target channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, target) channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([cs.CHANNEL_IFACE_DESTROYABLE, cs.CHANNEL_IFACE_GROUP, ],signature='s') chan = SimulatedChannel(conn, channel_properties, group=True) chan.announce() e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete'], handlers e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) # What does the policy service think? permission = q.expect('dbus-method-call', path='/com/example/Policy', interface='com.example.Policy', method='RequestPermission') # Think about it for a bit sync_dbus(bus, q, account) # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, signature='') q.dbus_return(e.message, signature='') # Let the test code decide how to reply return permission, chan, cdo_path
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) 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 announce_common(q, bus, empathy, kopete, account, conn, cd_props, urgent=False): if urgent: jid = 'friar.lawrence' else: jid = 'juliet' channel_properties = dbus.Dictionary(contact_text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = jid channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, jid) channel_properties[cs.CHANNEL + '.InitiatorID'] = jid channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, jid) channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') if urgent: channel_properties['com.example.Urgency.Urgent'] = True chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] if urgent: # The handler with BypassApproval is first assert handlers[0] == cs.tp_name_prefix + '.Client.Kopete.BypassApproval' # Kopete's filter is more specific than Empathy's, so it comes next assert handlers[1] == cs.tp_name_prefix + '.Client.Kopete' # Empathy's filter is the least specific, so it's last assert handlers[2] == cs.tp_name_prefix + '.Client.Empathy' assert len(handlers) == 3 else: handlers.sort() assert handlers == [cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete'], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args return cdo_iface, chan, channel_properties, [e, k]
def test(q, bus, 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_channel_creation(q, bus, account, client, conn, yours_first=True, swap_requests=False): user_action_time1 = dbus.Int64(1238582606) user_action_time2 = dbus.Int64(1244444444) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) # chat UI calls ChannelDispatcher.EnsureChannel request = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, 'EnsureChannel', account.object_path, request, user_action_time1, client.bus_name, dbus_interface=cs.CD) ret = q.expect('dbus-return', method='EnsureChannel') request_path = ret.value[0] # chat UI connects to signals and calls ChannelRequest.Proceed() cr1 = bus.get_object(cs.AM, request_path) request_props = cr1.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time1 assert request_props['PreferredHandler'] == client.bus_name assert request_props['Interfaces'] == [] cr1.Proceed(dbus_interface=cs.CR) cm_request_call1, add_request_call1 = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=client.object_path), ) # Before the first request has succeeded, the user gets impatient and # the UI re-requests. call_async(q, cd, 'EnsureChannel', account.object_path, request, user_action_time2, client.bus_name, dbus_interface=cs.CD) ret = q.expect('dbus-return', method='EnsureChannel') request_path = ret.value[0] cr2 = bus.get_object(cs.AM, request_path) request_props = cr2.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time2 assert request_props['PreferredHandler'] == client.bus_name assert request_props['Interfaces'] == [] cr2.Proceed(dbus_interface=cs.CR) cm_request_call2, add_request_call2 = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=client.object_path), ) assert add_request_call1.args[0] == cr1.object_path request_props1 = add_request_call1.args[1] assert request_props1[cs.CR + '.Account'] == account.object_path assert request_props1[cs.CR + '.Requests'] == [request] assert request_props1[cs.CR + '.UserActionTime'] == user_action_time1 assert request_props1[cs.CR + '.PreferredHandler'] == client.bus_name assert request_props1[cs.CR + '.Interfaces'] == [] assert add_request_call2.args[0] == cr2.object_path request_props2 = add_request_call2.args[1] assert request_props2[cs.CR + '.Account'] == account.object_path assert request_props2[cs.CR + '.Requests'] == [request] assert request_props2[cs.CR + '.UserActionTime'] == user_action_time2 assert request_props2[cs.CR + '.PreferredHandler'] == client.bus_name assert request_props2[cs.CR + '.Interfaces'] == [] q.dbus_return(add_request_call1.message, signature='') q.dbus_return(add_request_call2.message, signature='') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # Having announce() (i.e. NewChannels) come last is guaranteed by # telepathy-spec (since 0.17.14). There is no other ordering guarantee. if swap_requests: m2, m1 = cm_request_call1.message, cm_request_call2.message else: m1, m2 = cm_request_call1.message, cm_request_call2.message q.dbus_return(m1, yours_first, channel.object_path, channel.immutable, signature='boa{sv}') q.dbus_return(m2, not yours_first, channel.object_path, channel.immutable, signature='boa{sv}') channel.announce() # Observer should get told, processing waits for it e = q.expect('dbus-method-call', path=client.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == '/', e.args # no dispatch operation assert sorted(e.args[4]) == sorted([cr1.object_path, cr2.object_path]), e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel.immutable, channels # Observer says "OK, go" q.dbus_return(e.message, signature='') # Handler is next e = q.expect('dbus-method-call', path=client.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels assert sorted(e.args[3]) == sorted([cr1.object_path, cr2.object_path]), e.args assert e.args[4] == user_action_time2, (e.args[4], user_action_time2) assert isinstance(e.args[5], dict) assertContains('request-properties', e.args[5]) assertContains(cr1.object_path, e.args[5]['request-properties']) assertContains(cr2.object_path, e.args[5]['request-properties']) assertLength(2, e.args[5]['request-properties']) assertEquals(request_props1, e.args[5]['request-properties'][cr1.object_path]) assertEquals(request_props2, e.args[5]['request-properties'][cr2.object_path]) assert len(e.args) == 6 # Handler accepts the Channels q.dbus_return(e.message, signature='') # CR emits Succeeded q.expect('dbus-signal', path=request_path, interface=cs.CR, signal='Succeeded') return channel
def test(q, bus, 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') # Empathy is an observer for text channels with # DelayApprovers=TRUE. empathy = SimulatedClient(q, bus, 'Empathy', observe=[text_fixed_properties], approve=[], handle=[], delay_approvers=True) # Kopete is an approver and handler for text channels. kopete = SimulatedClient(q, bus, 'Kopete', observe=[], approve=[text_fixed_properties], handle=[text_fixed_properties]) expect_client_setup(q, [empathy, kopete]) # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # A text channel appears! channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) # Empathy, the observer, gets the channel to observe. Because it # has DelayApprovers=TRUE, Kopete should not have # AddDispatchOperation called on it until Empathy returns from # ObserveChannels. forbidden = [EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation')] q.forbid_events(forbidden) o = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False) # Waste a little time here and there. We can't call sync_dbus # here because it calls Ping and libdbus returns from Ping # synchronously and doesn't turn the main loop handle enough. call_async(q, cd_props, 'Get', cs.CD_IFACE_OP_LIST, 'DispatchOperations') event = q.expect('dbus-return', method='Get') # Finally return from ObserveChannels, so now we expect ADO to be # called on Kopete. q.dbus_return(o.message, bus=bus, signature='') q.unforbid_events(forbidden) e = q.expect('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False) q.dbus_return(e.message, bus=bus, signature='') # The user responds to Kopete call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Kopete') # Kopete is asked to handle the channels k = q.expect('dbus-method-call', path=kopete.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Kopete accepts the channels q.dbus_return(k.message, bus=bus, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWith'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
def test(q, bus, mc): params = dbus.Dictionary({"account": "*****@*****.**", "password": "******"}, signature='sv') simulated_cm, account = create_fakecm_account(q, bus, mc, params) conn = enable_fakecm_account(q, bus, mc, account, params) text_fixed_properties = dbus.Dictionary({ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, }, signature='sv') # Empathy Chat is a text handler empathy_bus = dbus.bus.BusConnection() empathy = SimulatedClient(q, empathy_bus, 'EmpathyChat', handle=[text_fixed_properties], bypass_approval=False) q.attach_to_bus(empathy_bus) # gnome-shell is a text approver and handler gs = SimulatedClient(q, bus, 'GnomeShell', approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy, gs]) cd = ChannelDispatcher(bus) # incoming text channel channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # gnome-shell's approver is notified e = q.expect('dbus-method-call', path=gs.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False) channels, cdo_path,props = e.args cdo = ChannelDispatchOperation(bus, cdo_path) q.dbus_return(e.message, signature='') # gnome-shell handles the channel itself first call_async(q, cdo, 'HandleWith', cs.tp_name_prefix + '.Client.GnomeShell') e = q.expect('dbus-method-call', path=gs.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) q.dbus_return(e.message, signature='') # test delegating an incoming channel test_delegate_channel(q, bus, mc, account, conn, chan, empathy, empathy_bus, gs) # Empathy is back empathy = SimulatedClient(q, empathy_bus, 'EmpathyChat', handle=[text_fixed_properties], bypass_approval=False) expect_client_setup(q, [empathy]) # gnome-shell requests a channel for itself call_async(q, cd, 'CreateChannelWithHints', account.object_path, REQUEST, 0, cs.tp_name_prefix + '.Client.GnomeShell', {}) e = q.expect('dbus-return', method='CreateChannelWithHints') cr = ChannelRequest(bus, e.value[0]) cr.Proceed() e = q.expect('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel', path=conn.object_path, args=[REQUEST], handled=False) # channel is created chan = SimulatedChannel(conn, REQUEST) q.dbus_return(e.message, chan.object_path, chan.immutable, signature='oa{sv}') chan.announce() # gnome-shell handles the channel e = q.expect('dbus-method-call', path=gs.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) q.dbus_return(e.message, signature='') # test delegating an outgoing channel test_delegate_channel(q, bus, mc, account, conn, chan, empathy, empathy_bus, gs)
def test(q, bus, mc): params = dbus.Dictionary( { "account": "*****@*****.**", "password": "******" }, signature='sv') simulated_cm, account = create_fakecm_account(q, bus, mc, params) conn = enable_fakecm_account(q, bus, mc, account, params) text_fixed_properties = dbus.Dictionary( { cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL + '.Type.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') voip_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL, }, signature='sv') # Two clients want to observe, approve and handle text and VoIP channels. empathy = SimulatedClient(q, bus, 'Empathy', observe=[text_fixed_properties, voip_fixed_properties], approve=[text_fixed_properties, voip_fixed_properties], handle=[text_fixed_properties, voip_fixed_properties], bypass_approval=False) kopete = SimulatedClient(q, bus, 'Kopete', observe=[text_fixed_properties, voip_fixed_properties], approve=[text_fixed_properties, voip_fixed_properties], handle=[text_fixed_properties, voip_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy, kopete]) # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # First, a VoIP channel is created BUNDLE = '/8de0d29d-83e1-40f5-b24f-748c0aa86c82' channel_properties = dbus.Dictionary(voip_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') channel_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete'], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, signature='') q.dbus_return(e.message, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, signature='') q.dbus_return(k.message, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Empathy') # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWith'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # Now that Empathy has the VoIP channel, it wants to steal incoming Text # channels from the same bundle same_bundle_properties = dbus.Dictionary(text_fixed_properties, signature='sv') same_bundle_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE bypass = SimulatedClient(q, bus, 'Empathy._1_42.Window2', observe=[], approve=[], handle=[same_bundle_properties], bypass_approval=True) # wait for MC to download the properties expect_client_setup(q, [bypass]) # From now on, this test must fail if we're asked to approve anything approval = [ EventPattern('dbus-method-call', method='AddDispatchOperation'), ] q.forbid_events(approval) channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetHandleType'] = cs.HT_CONTACT channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # Again, there's a CDO e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] # The handler with BypassApproval is first assert handlers[0] == bypass.bus_name # The other two handlers are still possibilities assert len(handlers) == 3 # Observers are invoked as usual e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, signature='') q.dbus_return(e.message, signature='') # Empathy's BypassApproval part is asked to handle the channels e = q.expect('dbus-method-call', path=bypass.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, signature='')
channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) q.dbus_return(cm_request_call.message, channel.object_path, channel.immutable, signature='oa{sv}') channel.announce() # Channel is unwanted now, MC stabs it in the face stdsig, _ = q.expect_many( EventPattern('dbus-signal', path=request_path, interface=cs.CR, signal='Failed'), EventPattern('dbus-method-call', path=channel.object_path, interface=cs.CHANNEL, method='Close', handled=True), ) assert stdsig.args[0] == cs.CANCELLED
def test_dispatching(q, bus, conn, account, empathy, kopete): # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) ops = cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') assert ops == [], ops channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \ cdo_properties[cs.CDO + '.Interfaces'] assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path, channel_properties)] assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \ cdo_properties[cs.CDO + '.PossibleHandlers'] # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=empathy_bus, signature='') q.dbus_return(e.message, bus=kopete_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Empathy') # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, bus=empathy_bus, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWith'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
def test(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) 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_channel_creation(q, bus, account, client, conn, ensure=False, prefer=None, channel_type=cs.CHANNEL_TYPE_TEXT): user_action_time = dbus.Int64(1238582606) if prefer is None: prefer = client cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) # chat UI calls ChannelDispatcher.EnsureChannel or CreateChannel request = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': channel_type, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, (ensure and 'EnsureChannel' or 'CreateChannel'), account.object_path, request, user_action_time, prefer.bus_name, dbus_interface=cs.CD) ret = q.expect('dbus-return', method=(ensure and 'EnsureChannel' or 'CreateChannel')) request_path = ret.value[0] # chat UI connects to signals and calls ChannelRequest.Proceed() cr = bus.get_object(cs.AM, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == prefer.bus_name assert request_props['Interfaces'] == [] cr.Proceed(dbus_interface=cs.CR) # FIXME: should the EnsureChannel/CreateChannel call, and the AddRequest # call, be in a defined order? Probably not though, since CMs and Clients # aren't meant to be the same process! cm_request_call, add_request_call = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method=(ensure and 'EnsureChannel' or 'CreateChannel'), path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest'), ) assert add_request_call.args[0] == request_path assert add_request_call.path == prefer.object_path request_props = add_request_call.args[1] assert request_props[cs.CR + '.Account'] == account.object_path assert request_props[cs.CR + '.Requests'] == [request] assert request_props[cs.CR + '.UserActionTime'] == user_action_time assert request_props[cs.CR + '.PreferredHandler'] == prefer.bus_name assert request_props[cs.CR + '.Interfaces'] == [] q.dbus_return(add_request_call.message, signature='') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) if ensure: q.dbus_return( cm_request_call.message, True, # <- Yours channel.object_path, channel.immutable, signature='boa{sv}') else: # Create q.dbus_return(cm_request_call.message, channel.object_path, channel.immutable, signature='oa{sv}') channel.announce() if channel_type == cs.CHANNEL_TYPE_TEXT: # Observer should get told, processing waits for it e = q.expect('dbus-method-call', path=client.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == '/', e.args # no dispatch operation assert e.args[4] == [request_path], e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels # Observer says "OK, go" q.dbus_return(e.message, signature='') # Handler is next e = q.expect('dbus-method-call', path=prefer.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels assert e.args[3] == [request_path], e.args assert e.args[4] == user_action_time assert isinstance(e.args[5], dict) assertContains('request-properties', e.args[5]) assertContains(request_path, e.args[5]['request-properties']) assertLength(1, e.args[5]['request-properties']) assertEquals(request_props, e.args[5]['request-properties'][request_path]) assert len(e.args) == 6 # Handler accepts the Channels q.dbus_return(e.message, signature='') # SucceededWithChannel is fired first e = q.expect('dbus-signal', path=request_path, interface=cs.CR, signal='SucceededWithChannel') assertEquals(conn.object_path, e.args[0]) assert isinstance(e.args[1], dict), e.args[1] assertEquals(channel.object_path, e.args[2]) assertEquals(channel_immutable, e.args[3]) # CR emits Succeeded q.expect('dbus-signal', path=request_path, interface=cs.CR, signal='Succeeded') # Close the channel channel.close()
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) 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 announce_common(q, bus, empathy, kopete, account, conn, cd_props, urgent=False): if urgent: jid = 'friar.lawrence' else: jid = 'juliet' channel_properties = dbus.Dictionary(contact_text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = jid channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, jid) channel_properties[cs.CHANNEL + '.InitiatorID'] = jid channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, jid) channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') if urgent: channel_properties['com.example.Urgency.Urgent'] = True chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] if urgent: # The handler with BypassApproval is first assert handlers[ 0] == cs.tp_name_prefix + '.Client.Kopete.BypassApproval' # Kopete's filter is more specific than Empathy's, so it comes next assert handlers[1] == cs.tp_name_prefix + '.Client.Kopete' # Empathy's filter is the least specific, so it's last assert handlers[2] == cs.tp_name_prefix + '.Client.Empathy' assert len(handlers) == 3 else: handlers.sort() assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args return cdo_iface, chan, channel_properties, [e, k]
def test(q, bus, 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) 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.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') voip_fixed_properties = dbus.Dictionary( { cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL, }, signature='sv') # Two clients want to observe, approve and handle text and VoIP channels. empathy = SimulatedClient( q, bus, 'Empathy', observe=[text_fixed_properties, voip_fixed_properties], approve=[text_fixed_properties, voip_fixed_properties], handle=[text_fixed_properties, voip_fixed_properties], bypass_approval=False) kopete = SimulatedClient( q, bus, 'Kopete', observe=[text_fixed_properties, voip_fixed_properties], approve=[text_fixed_properties, voip_fixed_properties], handle=[text_fixed_properties, voip_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy, kopete]) # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # First, a VoIP channel is created BUNDLE = '/8de0d29d-83e1-40f5-b24f-748c0aa86c82' channel_properties = dbus.Dictionary(voip_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') channel_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, signature='') q.dbus_return(e.message, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, signature='') q.dbus_return(k.message, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Empathy') # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWith'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # Now that Empathy has the VoIP channel, it wants to steal incoming Text # channels from the same bundle same_bundle_properties = dbus.Dictionary(text_fixed_properties, signature='sv') same_bundle_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE bypass = SimulatedClient(q, bus, 'Empathy._1_42.Window2', observe=[], approve=[], handle=[same_bundle_properties], bypass_approval=True) # wait for MC to download the properties expect_client_setup(q, [bypass]) # From now on, this test must fail if we're asked to approve anything approval = [ EventPattern('dbus-method-call', method='AddDispatchOperation'), ] q.forbid_events(approval) channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetHandleType'] = cs.HT_CONTACT channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.FUTURE.Bundle'] = BUNDLE channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # Again, there's a CDO e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] # The handler with BypassApproval is first assert handlers[0] == bypass.bus_name # The other two handlers are still possibilities assert len(handlers) == 3 # Observers are invoked as usual e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, signature='') q.dbus_return(e.message, signature='') # Empathy's BypassApproval part is asked to handle the channels e = q.expect('dbus-method-call', path=bypass.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, signature='')
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') empathy_bus = dbus.bus.BusConnection() empathy_bus.set_exit_on_disconnect(False) # we'll disconnect later kopete_bus = dbus.bus.BusConnection() q.attach_to_bus(empathy_bus) q.attach_to_bus(kopete_bus) # Two clients want to observe, approve and handle channels empathy = SimulatedClient(q, empathy_bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) kopete = SimulatedClient(q, kopete_bus, 'Kopete', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy, kopete]) # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \ cdo_properties[cs.CDO + '.Interfaces'] assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path, channel_properties)] assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \ cdo_properties[cs.CDO + '.PossibleHandlers'] # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=empathy_bus, signature='') q.dbus_return(e.message, bus=kopete_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # Using an invalid Handler name should fail call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.The.Moon.On.A.Stick') q.expect('dbus-error', method='HandleWith') call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.the moon on a stick') q.expect('dbus-error', method='HandleWith') # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Empathy') # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, bus=empathy_bus, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWith'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # Approve another channel using HandleWithTime() channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'lucien' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'lucien') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'lucien' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'lucien') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \ cdo_properties[cs.CDO + '.Interfaces'] assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path, channel_properties)] assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \ cdo_properties[cs.CDO + '.PossibleHandlers'] # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=empathy_bus, signature='') q.dbus_return(e.message, bus=kopete_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWithTime', cs.tp_name_prefix + '.Client.Empathy', 13) # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) account_path, conn_path, channels, requests, action_time, info = e.args assert action_time == 13 # Empathy accepts the channels q.dbus_return(e.message, bus=empathy_bus, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWithTime'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # From now on, it is an error to get HandleChannels (because we're # testing Claim()) forbidden = [ EventPattern('dbus-method-call', method='HandleChannels'), ] q.forbid_events(forbidden) # Another channel channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'mercutio' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'mercutio') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'mercutio' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'mercutio') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') claimed_chan = SimulatedChannel(conn, channel_properties) claimed_chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == claimed_chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=kopete_bus, signature='') q.dbus_return(e.message, bus=empathy_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(claimed_chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first, and Empathy decides it wants the # channel for itself empathy_cdo = empathy_bus.get_object(cdo.bus_name, cdo.object_path) empathy_cdo_iface = dbus.Interface(empathy_cdo, cs.CDO) call_async(q, empathy_cdo_iface, 'Claim') q.expect_many( EventPattern('dbus-signal', path=cdo_path, signal='Finished'), EventPattern('dbus-signal', path=cs.CD_PATH, signal='DispatchOperationFinished', args=[cdo_path]), EventPattern('dbus-return', method='Claim'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # A third channel channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'benvolio' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'benvolio') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'benvolio' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'benvolio') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') third_chan = SimulatedChannel(conn, channel_properties) third_chan.announce() # third_chan should not be closed q.unforbid_events(forbidden) forbidden.append( EventPattern('dbus-method-call', method='Close', path=third_chan.object_path)) q.forbid_events(forbidden) # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) q.dbus_return(k.message, bus=kopete_bus, signature='') q.dbus_return(e.message, bus=empathy_bus, signature='') e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Kopete closes this one kopete_cdo = kopete_bus.get_object(cdo.bus_name, cdo.object_path) kopete_cdo_iface = dbus.Interface(kopete_cdo, cs.CDO) call_async(q, kopete_cdo_iface, 'Claim') q.expect_many( EventPattern('dbus-signal', path=cdo_path, signal='Finished'), EventPattern('dbus-signal', path=cs.CD_PATH, signal='DispatchOperationFinished', args=[cdo_path]), EventPattern('dbus-return', method='Claim'), ) # Empathy crashes empathy.release_name() e = q.expect( 'dbus-signal', signal='NameOwnerChanged', predicate=( lambda e: e.args[0] == empathy.bus_name and e.args[2] == ''), ) empathy_unique_name = e.args[1] empathy_bus.flush() empathy_bus.close() # In response, the channels that were being handled by Empathy are closed. # Kopete's channel is *not* closed. q.expect_many( EventPattern('dbus-signal', signal='NameOwnerChanged', predicate=(lambda e: e.args[0] == empathy_unique_name and e.args[2] == '')), EventPattern('dbus-method-call', path=chan.object_path, method='Close'), EventPattern('dbus-method-call', path=claimed_chan.object_path, method='Close'), ) sync_dbus(bus, q, mc) q.unforbid_events(forbidden)
def test(q, bus, mc): params = dbus.Dictionary({"account": "*****@*****.**", "password": "******"}, signature='sv') (simulated_cm, account) = create_fakecm_account(q, bus, mc, params) account_iface = dbus.Interface(account, cs.ACCOUNT) account_props = dbus.Interface(account, cs.PROPERTIES_IFACE) # Ensure that it's enabled but has offline RP and doesn't connect # automatically call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence', (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', '')) q.expect('dbus-return', method='Set') call_async(q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence', (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Testing automatic presence')) q.expect('dbus-return', method='Set') q.expect('dbus-signal', signal='AccountPropertyChanged', predicate=lambda e: e.args[0].get('AutomaticPresence', (None, None, None))[1] == 'busy') call_async(q, account_props, 'Set', cs.ACCOUNT, 'ConnectAutomatically', False) q.expect('dbus-return', method='Set') call_async(q, account_props, 'Set', cs.ACCOUNT, 'Enabled', True) q.expect('dbus-return', method='Set') q.expect('dbus-signal', signal='AccountPropertyChanged', predicate=lambda e: e.args[0].get('Enabled')) # Requesting a channel will put us online user_action_time = dbus.Int64(1238582606) cd = bus.get_object(cs.CD, cs.CD_PATH) request = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, 'CreateChannel', account.object_path, request, user_action_time, "", dbus_interface=cs.CD) ret = q.expect('dbus-return', method='CreateChannel') request_path = ret.value[0] cr = bus.get_object(cs.AM, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == "" assert request_props['Interfaces'] == [] # make sure RequestConnection doesn't get called until we Proceed events = [EventPattern('dbus-method-call', method='RequestConnection')] q.forbid_events(events) sync_dbus(bus, q, mc) q.unforbid_events(events) cr.Proceed(dbus_interface=cs.CR) e = q.expect('dbus-method-call', method='RequestConnection', args=['fakeprotocol', params], destination=cs.tp_name_prefix + '.ConnectionManager.fakecm', path=cs.tp_path_prefix + '/ConnectionManager/fakecm', interface=cs.tp_name_prefix + '.ConnectionManager', handled=False) conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_', 'myself', has_presence=True) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') q.expect('dbus-method-call', method='Connect', path=conn.object_path, handled=True) conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) conn.presence = dbus.Struct((cs.PRESENCE_AVAILABLE, 'available', ''), signature='uss') _, cm_request_call = q.expect_many( EventPattern('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', args=['busy', 'Testing automatic presence'], handled=True), EventPattern('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel', args=[request], handled=False), ) q.dbus_emit(conn.object_path, cs.CONN_IFACE_SIMPLE_PRESENCE, 'PresencesChanged', {conn.self_handle: (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Testing automatic presence')}, signature='a{u(uss)}') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) q.dbus_return(cm_request_call.message, channel.object_path, channel.immutable, signature='oa{sv}') channel.announce() # there's no handler, so it gets shot down q.expect('dbus-method-call', path=channel.object_path, method='Close', handled=True)
def test(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): 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) 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_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) 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_channel_creation(q, bus, account, client, conn): user_action_time = dbus.Int64(1238582606) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) # chat UI calls ChannelDispatcher.EnsureChannel request = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, 'EnsureChannel', account.object_path, request, user_action_time, client.bus_name, dbus_interface=cs.CD) ret = q.expect('dbus-return', method='EnsureChannel') request_path = ret.value[0] # chat UI connects to signals and calls ChannelRequest.Proceed() cr = bus.get_object(cs.AM, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == client.bus_name assert request_props['Interfaces'] == [] cr.Proceed(dbus_interface=cs.CR) cm_request_call, add_request_call = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=client.object_path), ) assert add_request_call.args[0] == request_path request_props = add_request_call.args[1] assert request_props[cs.CR + '.Account'] == account.object_path assert request_props[cs.CR + '.Requests'] == [request] assert request_props[cs.CR + '.UserActionTime'] == user_action_time assert request_props[cs.CR + '.PreferredHandler'] == client.bus_name assert request_props[cs.CR + '.Interfaces'] == [] q.dbus_return(add_request_call.message, signature='') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) q.dbus_return( cm_request_call.message, True, # <- Yours channel.object_path, channel.immutable, signature='boa{sv}') channel.announce() # Observer should get told, processing waits for it e = q.expect('dbus-method-call', path=client.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == '/', e.args # no dispatch operation assert e.args[4] == [request_path], e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels # Observer says "OK, go" q.dbus_return(e.message, signature='') # Handler is next e = q.expect('dbus-method-call', path=client.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels assert e.args[3] == [request_path], e.args assert e.args[4] == user_action_time assert isinstance(e.args[5], dict) assert len(e.args) == 6 # Handler accepts the Channels q.dbus_return(e.message, signature='') # CR emits Succeeded q.expect('dbus-signal', path=request_path, interface=cs.CR, signal='Succeeded') return channel
def test_channel_creation(q, bus, account, client, conn, ensure): user_action_time = dbus.Int64(1238582606) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) # chat UI calls ChannelDispatcher.EnsureChannel or CreateChannel request = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, (ensure and 'EnsureChannel' or 'CreateChannel'), account.object_path, request, user_action_time, "", dbus_interface=cs.CD) ret = q.expect('dbus-return', method=(ensure and 'EnsureChannel' or 'CreateChannel')) request_path = ret.value[0] # chat UI connects to signals and calls ChannelRequest.Proceed() cr = bus.get_object(cs.AM, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == "" assert request_props['Interfaces'] == [] cr.Proceed(dbus_interface=cs.CR) # FIXME: should the EnsureChannel/CreateChannel call, and the AddRequest # call, be in a defined order? Probably not though, since CMs and Clients # aren't meant to be the same process! cm_request_call, add_request_call = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method=(ensure and 'EnsureChannel' or 'CreateChannel'), path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=client.object_path), ) assert add_request_call.args[0] == request_path request_props = add_request_call.args[1] assert request_props[cs.CR + '.Account'] == account.object_path assert request_props[cs.CR + '.Requests'] == [request] assert request_props[cs.CR + '.UserActionTime'] == user_action_time assert request_props[cs.CR + '.PreferredHandler'] == "" assert request_props[cs.CR + '.Interfaces'] == [] q.dbus_return(add_request_call.message, signature='') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) if ensure: q.dbus_return(cm_request_call.message, True, # <- Yours channel.object_path, channel.immutable, signature='boa{sv}') else: # Create q.dbus_return(cm_request_call.message, channel.object_path, channel.immutable, signature='oa{sv}') channel.announce() # Observer should get told, processing waits for it e = q.expect('dbus-method-call', path=client.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == '/', e.args # no dispatch operation assert e.args[4] == [request_path], e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels # Observer says "OK, go" q.dbus_return(e.message, signature='') # Handler is next e = q.expect('dbus-method-call', path=client.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels assert e.args[3] == [request_path], e.args assert e.args[4] == user_action_time assert isinstance(e.args[5], dict) assert len(e.args) == 6 # Handler accepts the Channels q.dbus_return(e.message, signature='') # CR emits Succeeded q.expect('dbus-signal', path=request_path, interface=cs.CR, signal='Succeeded') # Close the channel channel.close()
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): 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') == []
# Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) q.dbus_return(cm_request_call.message, channel.object_path, channel.immutable, signature='oa{sv}') channel.announce() # Channel is unwanted now, MC stabs it in the face stdsig, _ = q.expect_many( EventPattern('dbus-signal', path=request_path, interface=cs.CR, signal='Failed'), EventPattern('dbus-method-call', path=channel.object_path, interface=cs.CHANNEL, method='Close', handled=True), ) assert stdsig.args[0] == cs.CANCELLED if __name__ == '__main__': exec_test(test, {})
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.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.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) # One client (Kopete) has less specific filters than the other (Empathy), # to make sure that the dispatcher would normally prefer Empathy; this # means that when we use Kopete as the preferred handler, we know that # if Kopete is invoked, then preferring the preferred handler correctly # took precedence over the normal logic. vague_fixed_properties = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') text_fixed_properties = dbus.Dictionary( { cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') empathy_bus = dbus.bus.BusConnection() kopete_bus = dbus.bus.BusConnection() q.attach_to_bus(empathy_bus) q.attach_to_bus(kopete_bus) # Two clients want to observe, approve and handle channels empathy = SimulatedClient(q, empathy_bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) kopete = SimulatedClient(q, kopete_bus, 'Kopete', observe=[vague_fixed_properties], approve=[vague_fixed_properties], handle=[vague_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy, kopete]) # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] # Empathy has a more specific filter, so it comes first assert handlers == [ cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete' ], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \ cdo_properties[cs.CDO + '.Interfaces'] assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path, channel_properties)] assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \ cdo_properties[cs.CDO + '.PossibleHandlers'] # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=empathy_bus, signature='') q.dbus_return(e.message, bus=kopete_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention. However, the user is busy looking through the address # book, and independently decides to talk to Juliet. The address book # is from KDE so wants Kopete to be used. user_action_time = dbus.Int64(1238582606) request = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, 'EnsureChannel', account.object_path, request, user_action_time, kopete.bus_name, dbus_interface=cs.CD) ret, add_request_call = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=kopete.object_path), ) request_path = ret.value[0] assert add_request_call.args[0] == request_path request_props = add_request_call.args[1] assert request_props[cs.CR + '.Account'] == account.object_path assert request_props[cs.CR + '.Requests'] == [request] assert request_props[cs.CR + '.UserActionTime'] == user_action_time assert request_props[cs.CR + '.PreferredHandler'] == kopete.bus_name assert request_props[cs.CR + '.Interfaces'] == [] # UI connects to signals and calls ChannelRequest.Proceed() cr = bus.get_object(cs.AM, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == kopete.bus_name assert request_props['Interfaces'] == [] cr.Proceed(dbus_interface=cs.CR) cm_request_call = q.expect('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False) q.dbus_return(add_request_call.message, bus=kopete_bus, signature='') # Time passes. The CM returns the existing channel q.dbus_return(cm_request_call.message, False, chan.object_path, chan.immutable, signature='boa{sv}') # EnsureChannel constitutes approval, so Kopete is told to handle the # channel e = q.expect('dbus-method-call', path=kopete.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == chan.immutable, channels assert e.args[3] == [request_path], e.args assert e.args[4] == user_action_time, (e.args[4], user_action_time) assert isinstance(e.args[5], dict) assert len(e.args) == 6 q.dbus_return(e.message, bus=kopete_bus, signature='') q.expect_many( EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
def test(q, bus, mc): params = dbus.Dictionary({"account": "*****@*****.**", "password": "******"}, signature='sv') simulated_cm, account = create_fakecm_account(q, bus, mc, params) conn = enable_fakecm_account(q, bus, mc, account, params) text_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') empathy_bus = dbus.bus.BusConnection() empathy_bus.set_exit_on_disconnect(False) # we'll disconnect later kopete_bus = dbus.bus.BusConnection() q.attach_to_bus(empathy_bus) q.attach_to_bus(kopete_bus) # Two clients want to observe, approve and handle channels empathy = SimulatedClient(q, empathy_bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) kopete = SimulatedClient(q, kopete_bus, 'Kopete', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) # wait for MC to download the properties expect_client_setup(q, [empathy, kopete]) # subscribe to the OperationList interface (MC assumes that until this # property has been retrieved once, nobody cares) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete'], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \ cdo_properties[cs.CDO + '.Interfaces'] assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path, channel_properties)] assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \ cdo_properties[cs.CDO + '.PossibleHandlers'] # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=empathy_bus, signature='') q.dbus_return(e.message, bus=kopete_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # Using an invalid Handler name should fail call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.The.Moon.On.A.Stick') q.expect('dbus-error', method='HandleWith') call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.the moon on a stick') q.expect('dbus-error', method='HandleWith') # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWith', cs.tp_name_prefix + '.Client.Empathy') # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) # Empathy accepts the channels q.dbus_return(e.message, bus=empathy_bus, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWith'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # Approve another channel using HandleWithTime() channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'lucien' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'lucien') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'lucien' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'lucien') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') chan = SimulatedChannel(conn, channel_properties) chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete'], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) cdo_props_iface = dbus.Interface(cdo, cs.PROPERTIES_IFACE) assert cdo_props_iface.Get(cs.CDO, 'Interfaces') == \ cdo_properties[cs.CDO + '.Interfaces'] assert cdo_props_iface.Get(cs.CDO, 'Connection') == conn.object_path assert cdo_props_iface.Get(cs.CDO, 'Account') == account.object_path assert cdo_props_iface.Get(cs.CDO, 'Channels') == [(chan.object_path, channel_properties)] assert cdo_props_iface.Get(cs.CDO, 'PossibleHandlers') == \ cdo_properties[cs.CDO + '.PossibleHandlers'] # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=empathy_bus, signature='') q.dbus_return(e.message, bus=kopete_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first call_async(q, cdo_iface, 'HandleWithTime', cs.tp_name_prefix + '.Client.Empathy', 13) # Empathy is asked to handle the channels e = q.expect('dbus-method-call', path=empathy.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) account_path, conn_path, channels, requests, action_time, info = e.args assert action_time == 13 # Empathy accepts the channels q.dbus_return(e.message, bus=empathy_bus, signature='') q.expect_many( EventPattern('dbus-return', method='HandleWithTime'), EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'), EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST, signal='DispatchOperationFinished'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # From now on, it is an error to get HandleChannels (because we're # testing Claim()) forbidden = [ EventPattern('dbus-method-call', method='HandleChannels'), ] q.forbid_events(forbidden) # Another channel channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'mercutio' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'mercutio') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'mercutio' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'mercutio') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') claimed_chan = SimulatedChannel(conn, channel_properties) claimed_chan.announce() # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] assert cdo_properties[cs.CDO + '.Account'] == account.object_path assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path assert cs.CDO + '.Interfaces' in cdo_properties handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:] handlers.sort() assert handlers == [cs.tp_name_prefix + '.Client.Empathy', cs.tp_name_prefix + '.Client.Kopete'], handlers assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces') assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\ [(cdo_path, cdo_properties)] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) # Both Observers are told about the new channel e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == cdo_path, e.args assert e.args[4] == [], e.args # no requests satisfied channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == claimed_chan.object_path, channels assert channels[0][1] == channel_properties, channels assert k.args == e.args # Both Observers indicate that they are ready to proceed q.dbus_return(k.message, bus=kopete_bus, signature='') q.dbus_return(e.message, bus=empathy_bus, signature='') # The Approvers are next e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) assert e.args == [[(claimed_chan.object_path, channel_properties)], cdo_path, cdo_properties] assert k.args == e.args q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Both Approvers now have a flashing icon or something, trying to get the # user's attention # The user responds to Empathy first, and Empathy decides it wants the # channel for itself empathy_cdo = empathy_bus.get_object(cdo.bus_name, cdo.object_path) empathy_cdo_iface = dbus.Interface(empathy_cdo, cs.CDO) call_async(q, empathy_cdo_iface, 'Claim') q.expect_many( EventPattern('dbus-signal', path=cdo_path, signal='Finished'), EventPattern('dbus-signal', path=cs.CD_PATH, signal='DispatchOperationFinished', args=[cdo_path]), EventPattern('dbus-return', method='Claim'), ) # Now there are no more active channel dispatch operations assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == [] # A third channel channel_properties = dbus.Dictionary(text_fixed_properties, signature='sv') channel_properties[cs.CHANNEL + '.TargetID'] = 'benvolio' channel_properties[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'benvolio') channel_properties[cs.CHANNEL + '.InitiatorID'] = 'benvolio' channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'benvolio') channel_properties[cs.CHANNEL + '.Requested'] = False channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s') third_chan = SimulatedChannel(conn, channel_properties) third_chan.announce() # third_chan should not be closed q.unforbid_events(forbidden) forbidden.append(EventPattern('dbus-method-call', method='Close', path=third_chan.object_path)) q.forbid_events(forbidden) # A channel dispatch operation is created e = q.expect('dbus-signal', path=cs.CD_PATH, interface=cs.CD_IFACE_OP_LIST, signal='NewDispatchOperation') cdo_path = e.args[0] cdo_properties = e.args[1] cdo = bus.get_object(cs.CD, cdo_path) cdo_iface = dbus.Interface(cdo, cs.CDO) e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False), ) q.dbus_return(k.message, bus=kopete_bus, signature='') q.dbus_return(e.message, bus=empathy_bus, signature='') e, k = q.expect_many( EventPattern('dbus-method-call', path=empathy.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), EventPattern('dbus-method-call', path=kopete.object_path, interface=cs.APPROVER, method='AddDispatchOperation', handled=False), ) q.dbus_return(e.message, bus=empathy_bus, signature='') q.dbus_return(k.message, bus=kopete_bus, signature='') # Kopete closes this one kopete_cdo = kopete_bus.get_object(cdo.bus_name, cdo.object_path) kopete_cdo_iface = dbus.Interface(kopete_cdo, cs.CDO) call_async(q, kopete_cdo_iface, 'Claim') q.expect_many( EventPattern('dbus-signal', path=cdo_path, signal='Finished'), EventPattern('dbus-signal', path=cs.CD_PATH, signal='DispatchOperationFinished', args=[cdo_path]), EventPattern('dbus-return', method='Claim'), ) # Empathy crashes empathy.release_name() e = q.expect('dbus-signal', signal='NameOwnerChanged', predicate=(lambda e: e.args[0] == empathy.bus_name and e.args[2] == ''), ) empathy_unique_name = e.args[1] empathy_bus.flush() empathy_bus.close() # In response, the channels that were being handled by Empathy are closed. # Kopete's channel is *not* closed. q.expect_many( EventPattern('dbus-signal', signal='NameOwnerChanged', predicate=(lambda e: e.args[0] == empathy_unique_name and e.args[2] == '')), EventPattern('dbus-method-call', path=chan.object_path, method='Close'), EventPattern('dbus-method-call', path=claimed_chan.object_path, method='Close'), ) sync_dbus(bus, q, mc) q.unforbid_events(forbidden)
def test(q, bus, mc): # 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) 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.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) account_iface = dbus.Interface(account, cs.ACCOUNT) account_props = dbus.Interface(account, cs.PROPERTIES_IFACE) # Ensure that it's enabled but has offline RP and doesn't connect # automatically call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence', (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', '')) q.expect('dbus-return', method='Set') call_async( q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence', (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Testing automatic presence')) q.expect('dbus-return', method='Set') q.expect( 'dbus-signal', signal='AccountPropertyChanged', predicate=lambda e: e.args[0].get('AutomaticPresence', (None, None, None))[1] == 'busy') call_async(q, account_props, 'Set', cs.ACCOUNT, 'ConnectAutomatically', False) q.expect('dbus-return', method='Set') call_async(q, account_props, 'Set', cs.ACCOUNT, 'Enabled', True) q.expect('dbus-return', method='Set') q.expect('dbus-signal', signal='AccountPropertyChanged', predicate=lambda e: e.args[0].get('Enabled')) # Requesting a channel will put us online user_action_time = dbus.Int64(1238582606) cd = bus.get_object(cs.CD, cs.CD_PATH) request = dbus.Dictionary( { cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, 'CreateChannel', account.object_path, request, user_action_time, "", dbus_interface=cs.CD) ret = q.expect('dbus-return', method='CreateChannel') request_path = ret.value[0] cr = bus.get_object(cs.AM, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == "" assert request_props['Interfaces'] == [] # make sure RequestConnection doesn't get called until we Proceed events = [EventPattern('dbus-method-call', method='RequestConnection')] q.forbid_events(events) sync_dbus(bus, q, mc) q.unforbid_events(events) cr.Proceed(dbus_interface=cs.CR) e = q.expect('dbus-method-call', method='RequestConnection', args=['fakeprotocol', params], destination=cs.tp_name_prefix + '.ConnectionManager.fakecm', path=cs.tp_path_prefix + '/ConnectionManager/fakecm', interface=cs.tp_name_prefix + '.ConnectionManager', handled=False) conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_', 'myself', has_presence=True) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') q.expect('dbus-method-call', method='Connect', path=conn.object_path, handled=True) conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) conn.presence = dbus.Struct((cs.PRESENCE_AVAILABLE, 'available', ''), signature='uss') _, cm_request_call = q.expect_many( EventPattern('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', args=['busy', 'Testing automatic presence'], handled=True), EventPattern('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_REQUESTS, method='CreateChannel', args=[request], handled=False), ) q.dbus_emit(conn.object_path, cs.CONN_IFACE_SIMPLE_PRESENCE, 'PresencesChanged', { conn.self_handle: (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Testing automatic presence') }, signature='a{u(uss)}') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # this order of events is guaranteed by telepathy-spec (since 0.17.14) q.dbus_return(cm_request_call.message, channel.object_path, channel.immutable, signature='oa{sv}') channel.announce() # there's no handler, so it gets shot down q.expect('dbus-method-call', path=channel.object_path, method='Close', handled=True)
def test_channel_creation(q, bus, account, client, conn, yours_first=True, swap_requests=False): user_action_time1 = dbus.Int64(1238582606) user_action_time2 = dbus.Int64(1244444444) cd = bus.get_object(cs.CD, cs.CD_PATH) cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE) # chat UI calls ChannelDispatcher.EnsureChannel request = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') call_async(q, cd, 'EnsureChannel', account.object_path, request, user_action_time1, client.bus_name, dbus_interface=cs.CD) ret = q.expect('dbus-return', method='EnsureChannel') request_path = ret.value[0] # chat UI connects to signals and calls ChannelRequest.Proceed() cr1 = bus.get_object(cs.AM, request_path) request_props = cr1.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time1 assert request_props['PreferredHandler'] == client.bus_name assert request_props['Interfaces'] == [] cr1.Proceed(dbus_interface=cs.CR) cm_request_call1, add_request_call1 = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=client.object_path), ) # Before the first request has succeeded, the user gets impatient and # the UI re-requests. call_async(q, cd, 'EnsureChannel', account.object_path, request, user_action_time2, client.bus_name, dbus_interface=cs.CD) ret = q.expect('dbus-return', method='EnsureChannel') request_path = ret.value[0] cr2 = bus.get_object(cs.AM, request_path) request_props = cr2.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account.object_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time2 assert request_props['PreferredHandler'] == client.bus_name assert request_props['Interfaces'] == [] cr2.Proceed(dbus_interface=cs.CR) cm_request_call2, add_request_call2 = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False), EventPattern('dbus-method-call', handled=False, interface=cs.CLIENT_IFACE_REQUESTS, method='AddRequest', path=client.object_path), ) assert add_request_call1.args[0] == cr1.object_path request_props1 = add_request_call1.args[1] assert request_props1[cs.CR + '.Account'] == account.object_path assert request_props1[cs.CR + '.Requests'] == [request] assert request_props1[cs.CR + '.UserActionTime'] == user_action_time1 assert request_props1[cs.CR + '.PreferredHandler'] == client.bus_name assert request_props1[cs.CR + '.Interfaces'] == [] assert add_request_call2.args[0] == cr2.object_path request_props2 = add_request_call2.args[1] assert request_props2[cs.CR + '.Account'] == account.object_path assert request_props2[cs.CR + '.Requests'] == [request] assert request_props2[cs.CR + '.UserActionTime'] == user_action_time2 assert request_props2[cs.CR + '.PreferredHandler'] == client.bus_name assert request_props2[cs.CR + '.Interfaces'] == [] q.dbus_return(add_request_call1.message, signature='') q.dbus_return(add_request_call2.message, signature='') # Time passes. A channel is returned. channel_immutable = dbus.Dictionary(request) channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle channel_immutable[cs.CHANNEL + '.Requested'] = True channel_immutable[cs.CHANNEL + '.Interfaces'] = \ dbus.Array([], signature='s') channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ conn.ensure_handle(cs.HT_CONTACT, 'juliet') channel = SimulatedChannel(conn, channel_immutable) # Having announce() (i.e. NewChannels) come last is guaranteed by # telepathy-spec (since 0.17.14). There is no other ordering guarantee. if swap_requests: m2, m1 = cm_request_call1.message, cm_request_call2.message else: m1, m2 = cm_request_call1.message, cm_request_call2.message q.dbus_return(m1, yours_first, channel.object_path, channel.immutable, signature='boa{sv}') q.dbus_return(m2, not yours_first, channel.object_path, channel.immutable, signature='boa{sv}') channel.announce() # Observer should get told, processing waits for it e = q.expect('dbus-method-call', path=client.object_path, interface=cs.OBSERVER, method='ObserveChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args assert e.args[3] == '/', e.args # no dispatch operation assert sorted(e.args[4]) == sorted([cr1.object_path, cr2.object_path]), e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel.immutable, channels # Observer says "OK, go" q.dbus_return(e.message, signature='') # Handler is next e = q.expect('dbus-method-call', path=client.object_path, interface=cs.HANDLER, method='HandleChannels', handled=False) assert e.args[0] == account.object_path, e.args assert e.args[1] == conn.object_path, e.args channels = e.args[2] assert len(channels) == 1, channels assert channels[0][0] == channel.object_path, channels assert channels[0][1] == channel_immutable, channels assert sorted(e.args[3]) == sorted([cr1.object_path, cr2.object_path]), e.args assert e.args[4] == user_action_time2, (e.args[4], user_action_time2) assert isinstance(e.args[5], dict) assertContains('request-properties', e.args[5]) assertContains(cr1.object_path, e.args[5]['request-properties']) assertContains(cr2.object_path, e.args[5]['request-properties']) assertLength(2, e.args[5]['request-properties']) assertEquals(request_props1, e.args[5]['request-properties'][cr1.object_path]) assertEquals(request_props2, e.args[5]['request-properties'][cr2.object_path]) assert len(e.args) == 6 # Handler accepts the Channels q.dbus_return(e.message, signature='') # CR emits Succeeded q.expect('dbus-signal', path=request_path, interface=cs.CR, signal='Succeeded') return channel