def drop_and_expect_reconnect(q, bus, conn): # Connection falls over for a miscellaneous reason conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR) # MC reconnects 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', has_presence=True) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') # 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) return conn
def test(q, bus, mc): cm_bus = dbus.bus.BusConnection() cm_bus.set_exit_on_disconnect(False) # we'll disconnect later q.attach_to_bus(cm_bus) params = dbus.Dictionary( {"account": "*****@*****.**", "password": "******", }, signature='sv') (simulated_cm, account) = create_fakecm_account(q, bus, mc, params, cm_bus=cm_bus) account.Properties.Set(cs.ACCOUNT, 'Enabled', True) # Set online presence presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Fixing MC bugs'), signature='uss') account.Properties.Set(cs.ACCOUNT, 'RequestedPresence', presence) 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, cm_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) # Connect succeeds conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) # CM crashes conn.release_name() simulated_cm.release_name() cm_bus.flush() cm_bus.close() # MC should report the connection dying. e = q.expect('dbus-signal', signal='AccountPropertyChanged', predicate=lambda e: 'ConnectionError' in e.args[0]) changed, = e.args assertEquals('/', changed['Connection']) assertEquals(cs.CONN_STATUS_DISCONNECTED, changed['ConnectionStatus']) # In the absence of a better code, None will have to do. assertEquals(cs.CSR_NONE_SPECIFIED, changed['ConnectionStatusReason']) # And NoReply will do as “it crashed”. assertEquals(cs.DBUS_ERROR_NO_REPLY, changed['ConnectionError'])
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) 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, 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, unused, **kwargs): simulated_cm = SimulatedConnectionManager(q, bus) # make sure RequestConnection doesn't get called yet events = [EventPattern('dbus-method-call', method='RequestConnection')] q.forbid_events(events) fake_accounts_service = kwargs['fake_accounts_service'] preseed(q, bus, fake_accounts_service) # Wait for MC to load mc = MC(q, bus) # Trying to make a channel on account 1 doesn't work, because it's # not valid account_path = (cs.tp_path_prefix + '/Account/' + account1_id) cd = bus.get_object(cs.CD, cs.CD_PATH) 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, 'CreateChannel', account_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.CD, request_path) request_props = cr.GetAll(cs.CR, dbus_interface=cs.PROPERTIES_IFACE) assert request_props['Account'] == account_path assert request_props['Requests'] == [request] assert request_props['UserActionTime'] == user_action_time assert request_props['PreferredHandler'] == "" assert request_props['Interfaces'] == [] sync_dbus(bus, q, mc) cr.Proceed(dbus_interface=cs.CR) # FIXME: error isn't specified (NotAvailable perhaps?) q.expect('dbus-signal', path=cr.object_path, interface=cs.CR, signal='Failed') # Make account 1 valid: it should connect automatically account_path = (cs.tp_path_prefix + '/Account/' + account1_id) account = bus.get_object(cs.MC, account_path) sync_dbus(bus, q, mc) q.unforbid_events(events) call_async(q, account, 'UpdateParameters', {'password': '******'}, [], dbus_interface=cs.ACCOUNT) expected_params = { 'password': '******', 'account': '*****@*****.**' } e = q.expect('dbus-method-call', method='RequestConnection', args=['fakeprotocol', expected_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', 'account1', '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, interface=cs.CONN) conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) set_presence, e = q.expect_many( EventPattern('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', handled=True), EventPattern('dbus-signal', signal='AccountPropertyChanged', path=account_path, interface=cs.ACCOUNT, predicate=lambda e: 'CurrentPresence' in e.args[0] and e. args[0]['CurrentPresence'][2] != ''), ) assert e.args[0]['CurrentPresence'] == (cs.PRESENCE_AVAILABLE, 'available', 'My vision is augmented') # Request an online presence on account 2, then make it valid q.forbid_events(events) account_path = (cs.tp_path_prefix + '/Account/' + account2_id) account = bus.get_object(cs.MC, account_path) requested_presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Talking to Illuminati')) account.Set(cs.ACCOUNT, 'RequestedPresence', dbus.Struct(requested_presence, variant_level=1), dbus_interface=cs.PROPERTIES_IFACE) sync_dbus(bus, q, mc) q.unforbid_events(events) # Make the account valid call_async(q, account, 'UpdateParameters', {'password': '******'}, [], dbus_interface=cs.ACCOUNT) expected_params = { 'password': '******', 'account': '*****@*****.**' } e = q.expect('dbus-method-call', method='RequestConnection', args=['fakeprotocol', expected_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', 'account2', '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, interface=cs.CONN) conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) set_presence = q.expect('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', handled=True) e = q.expect('dbus-signal', signal='AccountPropertyChanged', path=account_path, interface=cs.ACCOUNT, predicate=lambda e: 'CurrentPresence' in e.args[0] and e.args[ 0]['CurrentPresence'][1] == 'busy') assert e.args[0]['CurrentPresence'] == (cs.PRESENCE_BUSY, 'busy', 'Talking to Illuminati')
def test(self, q, bus, mc): expected_params = { 'account': self.id, 'password': self.id, } account_path = (cs.ACCOUNT_PATH_PREFIX + self.id) account_proxy = bus.get_object(cs.AM, account_path) account_proxy.Set(cs.ACCOUNT, 'Enabled', True, dbus_interface=cs.PROPERTIES_IFACE) e = q.expect('dbus-method-call', method='RequestConnection', args=['fakeprotocol', expected_params], destination=cs.tp_name_prefix + '.ConnectionManager.fakecm', path=cs.tp_path_prefix + '/ConnectionManager/fakecm', interface=cs.tp_name_prefix + '.ConnectionManager', handled=False) if self.remote_avatar is None: initial_avatar = None elif self.remote_avatar: initial_avatar = dbus.Struct( (dbus.ByteArray(self.remote_avatar), 'text/plain'), signature='ays') else: initial_avatar = dbus.Struct((dbus.ByteArray(''), ''), signature='ays') conn = SimulatedConnection( q, bus, 'fakecm', 'fakeprotocol', self.id.replace('fakecm/fakeprotocol/', ''), 'myself', has_avatars=True, avatars_persist=self.avatars_persist, server_delays_avatar=self.server_delays, initial_avatar=initial_avatar, ) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') if self.winner != 'MC': q.forbid_events([ EventPattern('dbus-method-call', method='SetAvatar'), ]) if self.winner != 'service': q.forbid_events([ EventPattern('dbus-signal', signal='AvatarChanged', path=account_path), ]) q.expect('dbus-method-call', method='Connect', path=conn.object_path, handled=True, interface=cs.CONN) conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) if self.winner == 'MC': # MC should upload the avatar. _, e = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_AVATARS, method='SetAvatar', args=[self.local_avatar, 'image/jpeg'], handled=True), EventPattern( 'dbus-signal', signal='AccountPropertyChanged', path=account_path, interface=cs.ACCOUNT, predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs.CONN_STATUS_CONNECTED), ), ) elif self.winner == 'service': # We haven't changed the avatar since we last signed in, so we # don't set it - on the contrary, we pick up the remote avatar # (which has changed since we were last here) to store it in the # Account, unless the token says there is no avatar. if conn.avatar[0]: request_avatars_call, e = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_AVATARS, method='RequestAvatars', args=[[conn.self_handle]], handled=False), EventPattern( 'dbus-signal', signal='AccountPropertyChanged', path=account_path, interface=cs.ACCOUNT, predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs.CONN_STATUS_CONNECTED), ), ) q.dbus_return(request_avatars_call.message, signature='') q.dbus_emit(conn.object_path, cs.CONN_IFACE_AVATARS, 'AvatarRetrieved', conn.self_handle, str(conn.avatar[0]), dbus.ByteArray(conn.avatar[0]), conn.avatar[1], signature='usays') q.expect('dbus-signal', path=account_path, interface=cs.ACCOUNT_IFACE_AVATAR, signal='AvatarChanged'), account_props = dbus.Interface(account_proxy, cs.PROPERTIES_IFACE) assert account_props.Get(cs.ACCOUNT_IFACE_AVATAR, 'Avatar', byte_arrays=True) == conn.avatar sync_dbus(bus, q, mc) q.unforbid_all() if self.local_avatar: self.test_migration(bus, q, conn, account_proxy)
def test(q, bus, mc, **kwargs): # Create an account params = dbus.Dictionary( { "account": "*****@*****.**", "password": "******", "nickname": "albinoblacksheep", }, signature='sv') (simulated_cm, account) = create_fakecm_account(q, bus, mc, params) # 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) # 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('RequestedPresence') == requested_presence, \ properties.get('RequestedPresence') # Set some parameters. They include setting account to \\, as a regression # test for part of fd.o #28557. call_async(q, account, 'UpdateParameters', { 'account': r'\\', 'secret-mushroom': '/Amanita muscaria/', 'snakes': dbus.UInt32(42), 'com.example.Badgerable.Badgered': True, }, [], dbus_interface=cs.ACCOUNT) set_call, ret, _ = q.expect_many( EventPattern('dbus-method-call', path=conn.object_path, interface=cs.PROPERTIES_IFACE, method='Set', args=['com.example.Badgerable', 'Badgered', True], handled=False), EventPattern('dbus-return', method='UpdateParameters'), EventPattern('dbus-signal', path=account.object_path, interface=cs.ACCOUNT, signal='AccountPropertyChanged', args=[{ 'Parameters': { 'account': r'\\', 'com.example.Badgerable.Badgered': True, 'password': '******', 'nickname': 'albinoblacksheep', 'secret-mushroom': '/Amanita muscaria/', 'snakes': 42, } }]), ) # the D-Bus property should be set instantly; the others will take effect # on reconnection not_yet = ret.value[0] not_yet.sort() assert not_yet == ['account', 'secret-mushroom', 'snakes'], not_yet # Try to update 'account' to a value of the wrong type; MC should complain, # without having changed the value of 'snakes'. call_async(q, account, 'UpdateParameters', { 'account': dbus.UInt32(39), 'snakes': dbus.UInt32(39), }, [], dbus_interface=cs.ACCOUNT) q.expect('dbus-error', name=cs.INVALID_ARGUMENT) props = account.Get(cs.ACCOUNT, 'Parameters', dbus_interface=cs.PROPERTIES_IFACE) assertEquals(42, props['snakes']) # Try to update a parameter that doesn't exist; again, 'snakes' should not # be changed. call_async(q, account, 'UpdateParameters', { 'accccccount': dbus.UInt32(39), 'snakes': dbus.UInt32(39), }, [], dbus_interface=cs.ACCOUNT) q.expect('dbus-error', name=cs.INVALID_ARGUMENT) props = account.Get(cs.ACCOUNT, 'Parameters', dbus_interface=cs.PROPERTIES_IFACE) assertEquals(42, props['snakes']) # Unset some parameters, including a parameter which doesn't exist at all. # The spec says that “If the given parameters […] do not exist at all, the # account manager MUST accept this without error.” call_async(q, account, 'UpdateParameters', {}, ['nickname', 'com.example.Badgerable.Badgered', 'froufrou'], dbus_interface=cs.ACCOUNT) ret, _, _ = q.expect_many( EventPattern('dbus-return', method='UpdateParameters'), EventPattern('dbus-signal', path=account.object_path, interface=cs.ACCOUNT, signal='AccountPropertyChanged', args=[{ 'Parameters': { 'account': r'\\', 'password': '******', 'secret-mushroom': '/Amanita muscaria/', 'snakes': 42, } }]), EventPattern('dbus-method-call', path=conn.object_path, interface=cs.PROPERTIES_IFACE, method='Set', args=['com.example.Badgerable', 'Badgered', False], handled=False), ) # Because com.example.Badgerable.Badgered has a default value (namely # False), unsetting that parameter should cause the default value to be set # on the CM. not_yet = ret.value[0] assertEquals(['nickname'], not_yet) # Set contrived-example to its default value; since there's been no # practical change, we shouldn't be told we need to reconnect to apply it. call_async(q, account, 'UpdateParameters', {'contrived-example': dbus.UInt32(5)}, []) ret, _ = q.expect_many( EventPattern('dbus-return', method='UpdateParameters'), EventPattern('dbus-signal', path=account.object_path, interface=cs.ACCOUNT, signal='AccountPropertyChanged', args=[{ 'Parameters': { 'account': r'\\', 'password': '******', 'secret-mushroom': '/Amanita muscaria/', 'snakes': 42, "contrived-example": 5, } }]), ) not_yet = ret.value[0] assertEquals([], not_yet) # Unset contrived-example; again, MC should be smart enough to know we # don't need to do anything. call_async(q, account, 'UpdateParameters', {}, ['contrived-example']) ret, _ = q.expect_many( EventPattern('dbus-return', method='UpdateParameters'), EventPattern('dbus-signal', path=account.object_path, interface=cs.ACCOUNT, signal='AccountPropertyChanged', args=[{ 'Parameters': { 'account': r'\\', 'password': '******', 'secret-mushroom': '/Amanita muscaria/', 'snakes': 42, } }]), ) not_yet = ret.value[0] assertEquals([], not_yet) # Unset contrived-example again; the spec decrees that “If the given # parameters were not, in fact, stored, […] the account manager MUST accept # this without error.” call_async(q, account, 'UpdateParameters', {}, ['contrived-example']) ret = q.expect('dbus-return', method='UpdateParameters') not_yet = ret.value[0] assertEquals([], not_yet) cache_dir = os.environ['XDG_CACHE_HOME'] # Now that we're using GVariant-based storage, the backslashes aren't # escaped. assertEquals( r'\\', kwargs['fake_accounts_service'].accounts[account.object_path[ len(cs.ACCOUNT_PATH_PREFIX):]].params['account']) assertEquals( None, kwargs['fake_accounts_service'].accounts[account.object_path[ len(cs.ACCOUNT_PATH_PREFIX):]].untyped_params.get('account', None))
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, unused, **kwargs): simulated_cm = SimulatedConnectionManager(q, bus) fake_accounts_service = kwargs['fake_accounts_service'] preseed(q, bus, fake_accounts_service) expected_params = { 'account': '*****@*****.**', 'password': r'\\ionstorm\\', } mc = MC(q, bus, wait_for_names=False) mc.wait_for_names( # Migration step: the three separate attributes get combined # (before the names are taken, so we need to expect it here) EventPattern( 'dbus-method-call', interface=cs.TEST_DBUS_ACCOUNT_SERVICE_IFACE, method='UpdateAttributes', predicate=( lambda e: e.args[0] == account_id and e.args[1] == { 'AutomaticPresence': (2, 'available', 'My vision is augmented') } and e.args[2] == { 'AutomaticPresence': 0 } and # flags set(e.args[3]) == set([ # no particular order 'AutomaticPresenceType', 'AutomaticPresenceStatus', 'AutomaticPresenceMessage', ])))) request_conn, prop_changed = q.expect_many( EventPattern('dbus-method-call', method='RequestConnection', args=['fakeprotocol', expected_params], destination=cs.tp_name_prefix + '.ConnectionManager.fakecm', path=cs.tp_path_prefix + '/ConnectionManager/fakecm', interface=cs.tp_name_prefix + '.ConnectionManager', handled=False), EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=(lambda e: 'ConnectionStatus' in e.args[0])), ) conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_', 'myself', has_presence=True, has_aliasing=True, has_avatars=True) assertEquals('/', prop_changed.args[0].get('Connection')) assertEquals('', prop_changed.args[0].get('ConnectionError')) assertEquals({}, prop_changed.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_CONNECTING, prop_changed.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_REQUESTED, prop_changed.args[0].get('ConnectionStatusReason')) q.dbus_return(request_conn.message, conn.bus_name, conn.object_path, signature='so') account_path = (cs.tp_path_prefix + '/Account/' + account_id) account = bus.get_object(cs.tp_name_prefix + '.AccountManager', account_path) prop_changed, _ = q.expect_many( EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=(lambda e: 'ConnectionStatus' in e.args[0])), EventPattern('dbus-method-call', method='Connect', path=conn.object_path, handled=True, interface=cs.CONN), ) assertEquals(conn.object_path, prop_changed.args[0].get('Connection')) assertEquals('', prop_changed.args[0].get('ConnectionError')) assertEquals({}, prop_changed.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_CONNECTING, prop_changed.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_REQUESTED, prop_changed.args[0].get('ConnectionStatusReason')) props = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE) assert props['Connection'] == conn.object_path assert props['ConnectionStatus'] == cs.CONN_STATUS_CONNECTING assert props['ConnectionStatusReason'] == cs.CSR_REQUESTED print "becoming connected" conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) set_aliases, set_presence, set_avatar, prop_changed = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_ALIASING, method='SetAliases', args=[{ conn.self_handle: 'JC' }], handled=False), EventPattern('dbus-method-call', path=conn.object_path, interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', handled=True), EventPattern('dbus-method-call', interface=cs.CONN_IFACE_AVATARS, method='SetAvatar', args=['Deus Ex', 'image/jpeg'], handled=True), EventPattern( 'dbus-signal', signal='AccountPropertyChanged', path=account_path, interface=cs.ACCOUNT, predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs. CONN_STATUS_CONNECTED), ), ) assertEquals(conn.object_path, prop_changed.args[0].get('Connection')) assertEquals('', prop_changed.args[0].get('ConnectionError')) assertEquals({}, prop_changed.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_CONNECTED, prop_changed.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_REQUESTED, prop_changed.args[0].get('ConnectionStatusReason')) assert account.Get( cs.ACCOUNT, 'CurrentPresence', dbus_interface=cs.PROPERTIES_IFACE) == (cs.PRESENCE_AVAILABLE, 'available', 'My vision is augmented') q.dbus_return(set_aliases.message, signature='')
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): # Create an account (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) call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', False, dbus_interface=cs.PROPERTIES_IFACE) q.expect('dbus-return', method='Set') # Enable the account call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', True, dbus_interface=cs.PROPERTIES_IFACE) # Set online presence presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Fixing MC bugs'), signature='uss') call_async(q, account, 'Set', cs.ACCOUNT, 'RequestedPresence', 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', has_presence=True) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') # 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) conn = drop_and_expect_reconnect(q, bus, conn) conn = drop_and_expect_reconnect(q, bus, conn) conn = drop_and_expect_reconnect(q, bus, conn) forbidden = [EventPattern('dbus-method-call', method='RequestConnection')] q.forbid_events(forbidden) # Connection falls over for a miscellaneous reason conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR) # Right, that's it, I'm giving up... # This test can be considered to have succeeded if we don't # RequestConnection again before the test fails due to timeout. try: q.expect('the end of the world') except TimeoutError: return else: raise AssertionError('An impossible event happened')
def test(q, bus, mc): # Create an account params = dbus.Dictionary( { "account": "*****@*****.**", "password": "******" }, signature='sv') (simulated_cm, account) = create_fakecm_account(q, bus, mc, params) # Events that indicate that Reconnect might have done something looks_like_reconnection = [ EventPattern('dbus-method-call', method='RequestConnection'), EventPattern('dbus-method-call', method='Disconnect'), ] q.forbid_events(looks_like_reconnection) # While we want to be online but the account is disabled, Reconnect is a # no-op. Set Enabled to False explicitly, so we're less reliant on initial # state. call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', False, dbus_interface=cs.PROPERTIES_IFACE) q.expect('dbus-return', method='Set') requested_presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_AVAILABLE), dbus.String(u'available'), dbus.String(u''))) call_async(q, account, 'Set', cs.ACCOUNT, 'RequestedPresence', requested_presence, dbus_interface=cs.PROPERTIES_IFACE) q.expect('dbus-return', method='Set') call_async(q, account, 'Reconnect', dbus_interface=cs.ACCOUNT) q.expect('dbus-return', method='Reconnect') sync_dbus(bus, q, account) # While we want to be offline but the account is enabled, Reconnect is # still a no-op. requested_presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_OFFLINE), dbus.String(u'offline'), dbus.String(u''))) call_async(q, account, 'Set', cs.ACCOUNT, 'RequestedPresence', requested_presence, dbus_interface=cs.PROPERTIES_IFACE) q.expect_many( EventPattern('dbus-return', method='Set'), EventPattern('dbus-signal', path=account.object_path, signal='AccountPropertyChanged', interface=cs.ACCOUNT), ) # Enable the account call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', True, dbus_interface=cs.PROPERTIES_IFACE) q.expect_many( EventPattern('dbus-return', method='Set'), EventPattern('dbus-signal', path=account.object_path, signal='AccountPropertyChanged', interface=cs.ACCOUNT), ) call_async(q, account, 'Reconnect', dbus_interface=cs.ACCOUNT) q.expect('dbus-return', method='Reconnect') sync_dbus(bus, q, account) # Actually go online now q.unforbid_events(looks_like_reconnection) requested_presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_AVAILABLE), 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('RequestedPresence') == requested_presence, \ properties.get('RequestedPresence') # Reconnect account.Reconnect(dbus_interface=cs.ACCOUNT) q.expect('dbus-method-call', method='Disconnect', path=conn.object_path, handled=True) 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) # The object path needs to be different from the first simulated # connection which we made above, because the object isn't removed # from this bus and it's actually hard to do so because it's not # really on a bus, it's on the queue. So let's just change the # object path and it's fine. conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', 'second', 'myself') q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') q.expect_many( EventPattern('dbus-method-call', interface=cs.PROPERTIES_IFACE, method='GetAll', args=[cs.CONN_IFACE_REQUESTS], path=conn.object_path, handled=True), ) q.expect('dbus-method-call', method='Connect', path=conn.object_path, handled=True) conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) # 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 q.expect('dbus-method-call', method='Disconnect', path=conn.object_path, handled=True) properties = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE) assert properties['Connection'] == '/' assert properties['ConnectionStatus'] == cs.CONN_STATUS_DISCONNECTED assert properties['CurrentPresence'] == requested_presence assert properties['RequestedPresence'] == requested_presence
def test(q, bus, mc): 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]) # Create an account 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) call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', False, dbus_interface=cs.PROPERTIES_IFACE) q.expect('dbus-return', method='Set') # Enable the account call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', True, dbus_interface=cs.PROPERTIES_IFACE) # Set online presence presence = dbus.Struct( (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Fixing MC bugs'), signature='uss') call_async(q, account, 'Set', cs.ACCOUNT, 'RequestedPresence', 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', 'first', 'myself') q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') 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) test_dispatching(q, bus, conn, account, empathy, kopete) # Connection falls over for a miscellaneous reason conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR) # MC reconnects 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', 'second', 'myself') q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') 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) test_dispatching(q, bus, conn, account, empathy, kopete)
def test(q, bus, mc): # Create an account. We're setting register=True here to verify # that after one successful connection, it'll be removed (fd.o #28118). params = dbus.Dictionary({"account": "*****@*****.**", "password": "******", "register": True}, signature='sv') (simulated_cm, account) = create_fakecm_account(q, bus, mc, params) call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', False) q.expect('dbus-return', method='Set') # Enable the account call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', True) # Set online presence presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Fixing MC bugs'), signature='uss') call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'RequestedPresence', presence) 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', has_presence=True) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') # 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) q.expect('dbus-method-call', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', args=list(presence[1:]), handled=True) # Connection falls over for a miscellaneous reason conn.ConnectionError('com.example.My.Network.Is.Full.Of.Eels', {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}) conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED, cs.CSR_NETWORK_ERROR) # MC reconnects. This time, we expect it to have deleted the 'register' # parameter. del params['register'] disconnected, connecting, e = q.expect_many( EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs.CONN_STATUS_DISCONNECTED), ), EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs.CONN_STATUS_CONNECTING), ), EventPattern('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), ) assertEquals('/', disconnected.args[0].get('Connection')) assertEquals('com.example.My.Network.Is.Full.Of.Eels', disconnected.args[0].get('ConnectionError')) assertEquals( {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, disconnected.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_DISCONNECTED, disconnected.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_NETWORK_ERROR, disconnected.args[0].get('ConnectionStatusReason')) assertEquals('/', connecting.args[0].get('Connection')) assertEquals('com.example.My.Network.Is.Full.Of.Eels', connecting.args[0].get('ConnectionError')) assertEquals( {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, connecting.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_CONNECTING, connecting.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_REQUESTED, connecting.args[0].get('ConnectionStatusReason')) # The object path needs to be different from the first simulated # connection which we made above, because the object isn't removed # from this bus and it's actually hard to do so because it's not # really on a bus, it's on the queue. So let's just change the # object path and it's fine. conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', 'second', 'myself', has_presence=True) q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') # MC prepares the connection, does any pre-Connect setup, then # calls Connect connecting, _ = q.expect_many( EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs.CONN_STATUS_CONNECTING), ), EventPattern('dbus-method-call', method='Connect', path=conn.object_path, handled=True), ) assertEquals(conn.object_path, connecting.args[0].get('Connection')) assertEquals('com.example.My.Network.Is.Full.Of.Eels', connecting.args[0].get('ConnectionError')) assertEquals( {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, connecting.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_CONNECTING, connecting.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_REQUESTED, connecting.args[0].get('ConnectionStatusReason')) assertEquals('com.example.My.Network.Is.Full.Of.Eels', account.Properties.Get(cs.ACCOUNT, 'ConnectionError')) assertEquals( {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, account.Properties.Get(cs.ACCOUNT, 'ConnectionErrorDetails')) # Connect succeeds conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) connected, _ = q.expect_many( EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=(lambda e: e.args[0].get('ConnectionStatus') == cs.CONN_STATUS_CONNECTED), ), EventPattern('dbus-method-call', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence', args=list(presence[1:]), handled=True), ) assertEquals(conn.object_path, connected.args[0].get('Connection')) assertEquals('', connected.args[0].get('ConnectionError')) assertEquals({}, connected.args[0].get('ConnectionErrorDetails')) assertEquals(cs.CONN_STATUS_CONNECTED, connected.args[0].get('ConnectionStatus')) assertEquals(cs.CSR_REQUESTED, connected.args[0].get('ConnectionStatusReason')) assertEquals('', account.Properties.Get(cs.ACCOUNT, 'ConnectionError')) assertEquals({}, account.Properties.Get(cs.ACCOUNT, 'ConnectionErrorDetails'))