"""Regression test for the unofficial Account.Interface.Requests API. Requests use cases from doc/request.txt in telepathy-spec: req1, "Chat from chat UI", in the successful case where Yours=True """ import dbus import dbus.service from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \ call_async from mctest import exec_test, SimulatedConnection, SimulatedClient, \ create_fakecm_account, enable_fakecm_account, SimulatedChannel import constants as cs def test(q, bus, mc): params = dbus.Dictionary({"account": "someguy@example.com", "password": "secrecy"}, signature='sv') cm_name_ref, account = create_fakecm_account(q, bus, mc, params) conn = enable_fakecm_account(q, bus, mc, account, params) text_fixed_properties = dbus.Dictionary({ cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, }, signature='sv') client = SimulatedClient(q, bus, 'Empathy', observe=[text_fixed_properties], approve=[text_fixed_properties], handle=[text_fixed_properties], bypass_approval=False) # wait for MC to download the properties q.expect_many( EventPattern('dbus-method-call', interface=cs.PROPERTIES_IFACE, method='Get', args=[cs.CLIENT, 'Interfaces'], path=client.object_path), EventPattern('dbus-method-call', interface=cs.PROPERTIES_IFACE, method='Get', args=[cs.APPROVER, 'ApproverChannelFilter'], path=client.object_path), EventPattern('dbus-method-call', interface=cs.PROPERTIES_IFACE, method='Get', args=[cs.HANDLER, 'HandlerChannelFilter'], path=client.object_path), EventPattern('dbus-method-call', interface=cs.PROPERTIES_IFACE, method='Get', args=[cs.OBSERVER, 'ObserverChannelFilter'], path=client.object_path), ) user_action_time = dbus.Int64(1238582606) # chat UI calls ChannelDispatcher.EnsureChannel # (or in this case, an equivalent non-standard method on the Account) request = dbus.Dictionary({ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, cs.CHANNEL + '.TargetID': 'juliet', }, signature='sv') account_requests = dbus.Interface(account, cs.ACCOUNT_IFACE_NOKIA_REQUESTS) call_async(q, account_requests, 'EnsureChannel', request, user_action_time, client.bus_name) # chat UI connects to signals and calls ChannelRequest.Proceed() - but not # in this non-standard API, which fires off the request instantly ret, ensure_call = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-method-call', interface=cs.CONN_IFACE_REQUESTS, method='EnsureChannel', path=conn.object_path, args=[request], handled=False), ) request_path = ret.value[0] # ChannelDispatcher calls AddRequest on chat UI; chat UI ignores it as the # request is already known to it. # FIXME: it is not, strictly speaking, an API guarantee that the Requests # call precedes this e = q.expect('dbus-method-call', handled=False, interface=cs.HANDLER, method='AddRequest', path=client.object_path) assert e.args[0] == request_path request_props = e.args[1] assert request_props[cs.CR + '.Account'] == account.object_path assert request_props[cs.CR + '.Requests'] == [request] assert request_props[cs.CR + '.PreferredHandler'] == client.bus_name assert request_props[cs.CR + '.UserActionTime'] == user_action_time q.dbus_return(e.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 + '.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(ensure_call.message, True, # <- Yours channel.object_path, channel.immutable, signature='boa{sv}') q.dbus_emit(conn.object_path, cs.CONN_IFACE_REQUESTS, 'NewChannels', [(channel.object_path, channel.immutable)], signature='a(oa{sv})') # FIXME: at this point something crashes with a NULL hash table while # calling ObserveChannels - _mcd_channel_get_immutable_properties returns # NULL, it appears # Observer should get told, processing waits for it # CR emits Succeeded (or in Mardy's version, Account emits Succeeded) # Approver should not be told anything # Handler should only be told after the observer says yes if __name__ == '__main__': exec_test(test, {})