def test(q, bus, conn): cm = bus.get_object(cs.CM + '.ring', tp_path_prefix + '/ConnectionManager/ring') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['tel']), set(protocols.keys())) protocol_names = unwrap(cm_iface.ListProtocols()) assertEquals(set(['tel']), set(protocol_names)) cm_params = cm_iface.GetParameters('tel') local_props = protocols['tel'] local_params = local_props[cs.PROTOCOL + '.Parameters'] assertEquals(cm_params, local_params) proto = bus.get_object(cm.bus_name, cm.object_path + '/tel') proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('tel', proto_props['VCardField']) assertEquals('Mobile Telephony', proto_props['EnglishName']) assertEquals('im-tel', proto_props['Icon']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces'])
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns=ns.ROSTER, query_name='query') result = make_result_iq(stream, event.stanza) item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' stream.send(result) stream.send(make_presence('*****@*****.**', 'SHA1SUM-FOR-AMY')) stream.send(make_presence('*****@*****.**', 'SHA1SUM-FOR-BOB')) stream.send(make_presence('*****@*****.**', None)) q.expect('dbus-signal', signal='AvatarUpdated') handles = conn.RequestHandles(1, [ '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**' ]) tokens = unwrap(conn.Avatars.GetAvatarTokens(handles)) assert tokens == ['SHA1SUM-FOR-AMY', 'SHA1SUM-FOR-BOB', '', ''] tokens = unwrap(conn.Avatars.GetKnownAvatarTokens(handles)) tokens = sorted(tokens.items()) assert tokens == [(2, 'SHA1SUM-FOR-AMY'), (3, 'SHA1SUM-FOR-BOB'), (4, u'')]
def test(q, bus, conn): cm = bus.get_object(cs.CM + '.ring', tp_path_prefix + '/ConnectionManager/ring') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['tel']), set(protocols.keys())) protocol_names = unwrap(cm_iface.ListProtocols()) assertEquals(set(['tel']), set(protocol_names)) cm_params = cm_iface.GetParameters('tel') local_props = protocols['tel'] local_params = local_props[cs.PROTOCOL + '.Parameters'] assertEquals(cm_params, local_params) proto = bus.get_object(cm.bus_name, cm.object_path + '/tel') proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in [ 'Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon' ]: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('tel', proto_props['VCardField']) assertEquals('Mobile Telephony', proto_props['EnglishName']) assertEquals('im-tel', proto_props['Icon']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces'])
def check_tube_in_tubes(tube, tubes): """ Check that 'tube' is in 'tubes', which should be the return value of ListTubes(). tube[0] may be None to check that a new-style tube is represented on the old interface (because you don't know what its id is in those cases) """ utube = unwrap(tube) if tube[0] is None: for t in tubes: if tube[1:] == t[1:]: return else: for t in tubes: if tube[0] != t[0]: continue pair = "\n %s,\n %s" % (utube, unwrap(t)) assert tube[1] == t[1], "self handles don't match: %s" % pair assert tube[2] == t[2], "tube types don't match: %s" % pair assert tube[3] == t[3], "services don't match: %s " % pair assert tube[4] == t[4], "parameters don't match: %s" % pair assert tube[5] == t[5], "states don't match: %s" % pair return assert False, "tube %s not in %s" % (unwrap (tube), unwrap (tubes))
def test(q, bus, conn, server): cm = bus.get_object(cs.CM + '.idle', tp_path_prefix + '/ConnectionManager/idle') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['irc']), set(protocols.keys())) protocol_names = unwrap(cm_iface.ListProtocols()) assertEquals(set(['irc']), set(protocol_names)) cm_params = cm_iface.GetParameters('irc') local_props = protocols['irc'] local_params = local_props[cs.PROTOCOL + '.Parameters'] assertEquals(cm_params, local_params) proto = bus.get_object(cm.bus_name, cm.object_path + '/irc') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in [ 'Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', 'VCardField', 'EnglishName', 'Icon' ]: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('x-irc', proto_props['VCardField']) assertEquals('IRC', proto_props['EnglishName']) assertEquals('im-irc', proto_props['Icon']) assertContains(cs.CONN_IFACE_ALIASING, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces']) assertEquals('robot101', unwrap(proto_iface.NormalizeContact('Robot101'))) call_async(q, proto_iface, 'IdentifyAccount', {'account': 'Robot101'}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = {'account': 'Robot101', 'server': 'irc.oftc.net'} acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals('*****@*****.**', acc_name) # Test validating 'username' test_params = { 'account': 'Robot101', 'server': 'irc.oftc.net', 'username': '******', } call_async(q, proto_iface, 'IdentifyAccount', test_params) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT)
def test(q, bus, conn, server): cm = bus.get_object(cs.CM + '.idle', tp_path_prefix + '/ConnectionManager/idle') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['irc']), set(protocols.keys())) protocol_names = unwrap(cm_iface.ListProtocols()) assertEquals(set(['irc']), set(protocol_names)) cm_params = cm_iface.GetParameters('irc') local_props = protocols['irc'] local_params = local_props[cs.PROTOCOL + '.Parameters'] assertEquals(cm_params, local_params) proto = bus.get_object(cm.bus_name, cm.object_path + '/irc') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('x-irc', proto_props['VCardField']) assertEquals('IRC', proto_props['EnglishName']) assertEquals('im-irc', proto_props['Icon']) assertContains(cs.CONN_IFACE_ALIASING, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces']) assertEquals('robot101', unwrap(proto_iface.NormalizeContact('Robot101'))) call_async(q, proto_iface, 'IdentifyAccount', {'account': 'Robot101'}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = {'account': 'Robot101', 'server': 'irc.oftc.net' } acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals('*****@*****.**', acc_name) # Test validating 'username' test_params = { 'account': 'Robot101', 'server': 'irc.oftc.net', 'username': '******', } call_async(q, proto_iface, 'IdentifyAccount', test_params) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT)
def signal_receiver(*args, **kw): queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface']))
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns=ns.ROSTER, query_name='query') result = make_result_iq(stream, event.stanza) item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' stream.send(result) stream.send(make_presence('*****@*****.**', 'SHA1SUM-FOR-AMY')) stream.send(make_presence('*****@*****.**', 'SHA1SUM-FOR-BOB')) stream.send(make_presence('*****@*****.**', None)) q.expect('dbus-signal', signal='AvatarUpdated') handles = conn.get_contact_handles_sync([ '*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**' ]) h2asv = conn.Contacts.GetContactAttributes(handles, [cs.CONN_IFACE_AVATARS], False) assertEquals('SHA1SUM-FOR-AMY', h2asv[handles[0]][cs.ATTR_AVATAR_TOKEN]) assertEquals('SHA1SUM-FOR-BOB', h2asv[handles[1]][cs.ATTR_AVATAR_TOKEN]) assertEquals('', h2asv[handles[2]][cs.ATTR_AVATAR_TOKEN]) assertEquals(None, h2asv[handles[3]].get(cs.ATTR_AVATAR_TOKEN)) tokens = unwrap(conn.Avatars.GetKnownAvatarTokens(handles)) tokens = sorted(tokens.items()) assert tokens == [(2, 'SHA1SUM-FOR-AMY'), (3, 'SHA1SUM-FOR-BOB'), (4, u'')]
def signal_receiver(*args, **kw): if kw['path'] == '/org/freedesktop/DBus' and \ kw['member'] == 'NameOwnerChanged': bus_name, old_name, new_name = args if new_name == '': for i, conn in enumerate(conns): stream = streams[i] jid = jids[i] if conn._requested_bus_name == bus_name: factory.lost_presence(stream, jid) break queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=[unwrap(arg) for arg in args], interface=kw['interface']))
def exec_test_deferred (funs, params, protocol=None, timeout=None): colourer = None if sys.stdout.isatty(): colourer = install_colourer() queue = servicetest.IteratingEventQueue(timeout) queue.verbose = ( os.environ.get('CHECK_TWISTED_VERBOSE', '') != '' or '-v' in sys.argv) bus = dbus.SessionBus() sim = Simulator() bus.add_signal_receiver( lambda *args, **kw: queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True ) try: for f in funs: conn = make_connection(bus, queue.append, params) f(queue, bus, conn) except Exception: import traceback traceback.print_exc() try: if colourer: sys.stdout = colourer.fh reactor.crash() # force Disconnect in case the test crashed and didn't disconnect # properly. We need to call this async because the BaseIRCServer # class must do something in response to the Disconnect call and if we # call it synchronously, we're blocking ourself from responding to the # quit method. servicetest.call_async(queue, conn, 'Disconnect') if 'RING_TEST_REFDBG' in os.environ: # we have to wait for the timeout so the process is properly # exited and refdbg can generate its report time.sleep(5.5) except dbus.DBusException: pass
def exec_test_deferred(funs, params, protocol=None, timeout=None): colourer = None if sys.stdout.isatty(): colourer = install_colourer() queue = servicetest.IteratingEventQueue(timeout) queue.verbose = (os.environ.get('CHECK_TWISTED_VERBOSE', '') != '' or '-v' in sys.argv) bus = dbus.SessionBus() sim = Simulator() bus.add_signal_receiver( lambda *args, **kw: queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True) try: for f in funs: conn = make_connection(bus, queue.append, params) f(queue, bus, conn) except Exception: import traceback traceback.print_exc() try: if colourer: sys.stdout = colourer.fh reactor.crash() # force Disconnect in case the test crashed and didn't disconnect # properly. We need to call this async because the BaseIRCServer # class must do something in response to the Disconnect call and if we # call it synchronously, we're blocking ourself from responding to the # quit method. servicetest.call_async(queue, conn, 'Disconnect') if 'RING_TEST_REFDBG' in os.environ: # we have to wait for the timeout so the process is properly # exited and refdbg can generate its report time.sleep(5.5) except dbus.DBusException: pass
def test(q, bus, conn, stream): cm = bus.get_object(cs.CM + '.gabble', tp_path_prefix + '/ConnectionManager/gabble') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['jabber']), set(protocols.keys())) protocol_names = unwrap(cm_iface.ListProtocols()) assertEquals(set(['jabber']), set(protocol_names)) cm_params = cm_iface.GetParameters('jabber') jabber_props = protocols['jabber'] jabber_params = jabber_props[cs.PROTOCOL + '.Parameters'] assertEquals(cm_params, jabber_params) proto = bus.get_object(cm.bus_name, cm.object_path + '/jabber') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = jabber_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('*****@*****.**', unwrap(proto_iface.NormalizeContact('[email protected]/Telepathy'))) # org.freedesktop.Telepathy.Protocol.Interface.Presence expected_status = {'available': (cs.PRESENCE_AVAILABLE, True, True), 'dnd' : (cs.PRESENCE_BUSY, True, True), 'unknown' : (cs.PRESENCE_UNKNOWN, False, False), 'away' : (cs.PRESENCE_AWAY, True, True), 'xa' : (cs.PRESENCE_EXTENDED_AWAY, True, True), 'chat' : (cs.PRESENCE_AVAILABLE, True, True), 'error' : (cs.PRESENCE_ERROR, False, False), 'offline' : (cs.PRESENCE_OFFLINE, False, False), 'testaway' : (cs.PRESENCE_AWAY, False, False), 'testbusy' : (cs.PRESENCE_BUSY, True, False), 'hidden' : (cs.PRESENCE_HIDDEN, True, True)} presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses'); assertEquals(expected_status, unwrap(presences)) # (Only) 'account' is mandatory for IdentifyAccount() call_async(q, proto_iface, 'IdentifyAccount', {}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = { 'account': 'test@localhost' } acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals(test_params['account'], acc_name) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}])
def test(q, bus, conn, sip): cm = bus.get_object(cs.CM + '.sofiasip', tp_path_prefix + '/ConnectionManager/sofiasip') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['sip']), set(protocols.keys())) local_props = protocols['sip'] proto = bus.get_object(cm.bus_name, cm.object_path + '/sip') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('x-sip', proto_props['VCardField']) assertEquals('SIP', proto_props['EnglishName']) assertEquals('im-sip', proto_props['Icon']) assertContains(cs.CONN_IFACE_ALIASING, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_CONTACTS, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces']) assertEquals('sip:[email protected]', unwrap(proto_iface.NormalizeContact('*****@*****.**'))) # Only account is mandatory call_async(q, proto_iface, 'IdentifyAccount', {}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = {'account': '*****@*****.**'} acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals('*****@*****.**', acc_name)
def do_one_search(q, bus, conn, stream, fields, expected_search_keys, terms, results): call_create(q, conn, server) ret, nc_sig = answer_extended_field_query(q, stream, server, fields) path, props = ret.value props = unwrap(props) assert props[cs.CONTACT_SEARCH_SERVER] == server, pformat(props) assert sorted(props[cs.CONTACT_SEARCH_ASK]) == expected_search_keys, \ sorted(props[cs.CONTACT_SEARCH_ASK]) assert cs.CONTACT_SEARCH_STATE not in props, pformat(props) c = make_channel_proxy(conn, path, 'Channel') c_props = dbus.Interface(c, cs.PROPERTIES_IFACE) c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_NOT_STARTED, state # We make a search. iq = make_search(q, c_search, c_props, server, terms) query = iq.firstChildElement() fields_sent = xpath.queryForNodes( '/iq/query[@xmlns="%s"]/x[@xmlns="%s"][@type="submit"]/field' % (ns.SEARCH, ns.X_DATA), iq) assert fields_sent is not None # check FORM_TYPE f = fields_sent[0] assert f['type'] == 'hidden' assert f['var'] == 'FORM_TYPE' value = f.firstChildElement() assert value.name == 'value' assert value.children[0] == ns.SEARCH # extract search fields search_fields = [] for f in fields_sent[1:]: value = f.firstChildElement() assert value.name == 'value' search_fields.append((f['var'], value.children[0])) # Server sends the results of the search. send_results_extended(stream, iq, results, fields) return search_fields, c, c_search, c_props
def signal_receiver(*args, **kw): if kw['path'] == '/org/freedesktop/DBus' and \ kw['member'] == 'NameOwnerChanged': bus_name, old_name, new_name = args if new_name == '': for i, conn in enumerate(conns): stream = streams[i] jid = jids[i] if conn._requested_bus_name == bus_name: factory.lost_presence(stream, jid) break queue.append(Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface']))
def prepare_test(event_func, register_cb, params=None): actual_params = { 'account': '[email protected]', 'password': '******', 'proxy-host': '127.0.0.1', 'port': dbus.UInt16(random.randint(9090, 9999)), 'local-ip-address': '127.0.0.1', 'transport': 'udp' } if params is not None: for k, v in params.items(): if v is None: actual_params.pop(k, None) else: actual_params[k] = v bus = dbus.SessionBus() conn = servicetest.make_connection(bus, event_func, 'sofiasip', 'sip', actual_params) bus.add_signal_receiver( lambda *args, **kw: event_func( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True ) port = int(actual_params['port']) sip = SipProxy(host=actual_params['proxy-host'], port=port) sip.event_func = event_func sip.registrar_handler = register_cb reactor.listenUDP(port, sip) return bus, conn, sip
def complete_search2(q, bus, conn, stream): # uses other, dataform specific, fields fields = [('given', 'text-single', 'Name', []), ('family', 'text-single', 'Family Name', []), ('nickname', 'text-single', 'Nickname', [])] expected_search_keys = ['nickname', 'x-n-family', 'x-n-given'] terms = { 'x-n-family': 'Threepwood' } g_results = { 'jid': g_jid, 'given': 'Guybrush', 'family': 'Threepwood', 'nickname': 'Fancy Pants', 'email': g_jid } f_results = { 'jid': f_jid, 'given': 'Frederick', 'family': 'Threepwood', 'nickname': 'Freddie', 'email': f_jid } results = { g_jid: g_results, f_jid: f_results } search_fields, chan, c_search, c_props = do_one_search (q, bus, conn, stream, fields, expected_search_keys, terms, results.values()) assert len(search_fields) == 1 assert ('family', 'Threepwood') in search_fields, search_fields e = q.expect('dbus-signal', signal='SearchResultReceived') infos = e.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("n", [], [r['family'], r['given'], "", "", ""]) in i, i_ assert ("nickname", [], [r['nickname']]) in i, i_ assert ("email", [], [r['email']]) in i, i_ assert ("x-n-family", [], [r['family']]) in i, i_ assert ("x-n-given", [], [r['given']]) in i, i_ assert len(i) == 5, i_ search_done(q, chan, c_search, c_props)
def exec_test_deferred (funs, params, protocol=None, timeout=None): colourer = None if sys.stdout.isatty(): colourer = install_colourer() queue = servicetest.IteratingEventQueue(timeout) queue.verbose = ( os.environ.get('CHECK_TWISTED_VERBOSE', '') != '' or '-v' in sys.argv) bus = dbus.SessionBus() # conn = make_connection(bus, queue.append, params) (server, port) = start_server(queue.append, protocol=protocol) bus.add_signal_receiver( lambda *args, **kw: queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True ) error = None try: for f in funs: conn = make_connection(bus, queue.append, params) f(queue, bus, conn, server) except Exception, e: import traceback traceback.print_exc() error = e
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns=ns.ROSTER, query_name='query') result = make_result_iq(stream, event.stanza) item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = result.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' stream.send(result) stream.send(make_presence('*****@*****.**', 'SHA1SUM-FOR-AMY')) stream.send(make_presence('*****@*****.**', 'SHA1SUM-FOR-BOB')) stream.send(make_presence('*****@*****.**', None)) q.expect('dbus-signal', signal='AvatarUpdated') handles = conn.get_contact_handles_sync( ['*****@*****.**', '*****@*****.**', '*****@*****.**', '*****@*****.**']) h2asv = conn.Contacts.GetContactAttributes(handles, [cs.CONN_IFACE_AVATARS], False) assertEquals('SHA1SUM-FOR-AMY', h2asv[handles[0]][cs.ATTR_AVATAR_TOKEN]) assertEquals('SHA1SUM-FOR-BOB', h2asv[handles[1]][cs.ATTR_AVATAR_TOKEN]) assertEquals('', h2asv[handles[2]][cs.ATTR_AVATAR_TOKEN]) assertEquals(None, h2asv[handles[3]].get(cs.ATTR_AVATAR_TOKEN)) tokens = unwrap(conn.Avatars.GetKnownAvatarTokens(handles)) tokens = sorted(tokens.items()) assert tokens == [(2, 'SHA1SUM-FOR-AMY'), (3, 'SHA1SUM-FOR-BOB'), (4, u'')]
def openfire_search(q, bus, conn, stream): # Openfire only supports one text field and a bunch of checkboxes fields = [('search', 'text-single', 'Search', []), ('Username', 'boolean', 'Username', []), ('Name', 'boolean', 'Name', []), ('Email', 'boolean', 'Email', [])] expected_search_keys = [''] terms = { '': '*badger*' } jid = '*****@*****.**' results = {jid : { 'jid': jid, 'Name': 'Badger Badger', 'Email': jid, 'Username': '******'}} search_fields, chan, c_search, c_props = do_one_search (q, bus, conn, stream, fields, expected_search_keys, terms, results.values()) assert len(search_fields) == 4 assert ('search', '*badger*') in search_fields, search_fields assert ('Username', '1') in search_fields, search_fields assert ('Name', '1') in search_fields, search_fields assert ('Email', '1') in search_fields, search_fields r = q.expect('dbus-signal', signal='SearchResultReceived') infos = r.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("fn", [], [r['Name']]) in i, i_ assert ("email", [], [r['Email']]) in i, i_ assert len(i) == 2
def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) self_handle = conn.GetSelfHandle() requests = dbus.Interface(conn, CONN_IFACE_REQUESTS) room_jid = '*****@*****.**' room_handle = request_muc_handle(q, conn, stream, room_jid) call_async(q, requests, 'CreateChannel', dbus.Dictionary({ CHANNEL_TYPE: CHANNEL_TYPE_TEXT, TARGET_HANDLE_TYPE: HT_ROOM, TARGET_HANDLE: room_handle, }, signature='sv')) expected_jid = '%s/%s' % (room_jid, 'test') q.expect('stream-presence', to=expected_jid) # Send presence for another member of the MUC stream.send(make_muc_presence('owner', 'moderator', room_jid, 'liz')) # This is a themed discussion, so the MUC server forces you to have an # appropriate name. self_presence = make_muc_presence('none', 'participant', room_jid, 'toofer') x = [elt for elt in self_presence.elements() if elt.name == 'x'][0] status = x.addElement('status') status['code'] = '110' # "This is you" status = x.addElement('status') status['code'] = '210' # "I renamed you. Muahaha." stream.send(self_presence) # Gabble should figure out from 110 that it's in the room, and from 210 # that we've been renamed. event = q.expect('dbus-return', method='CreateChannel') path, props = event.value text_chan = bus.get_object(conn.bus_name, path) group_props = unwrap(text_chan.GetAll(CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE)) liz, toofer, expected_handle = conn.RequestHandles(HT_CONTACT, ["%s/%s" % (room_jid, m) for m in ['liz', 'toofer', 'test']]) # Check that Gabble think our nickname in the room is toofer not test muc_self_handle = group_props['SelfHandle'] assert muc_self_handle == toofer, (muc_self_handle, toofer, expected_handle) members = group_props['Members'] # Check there are exactly two members (liz and toofer) expected_members = [liz, toofer] assert sorted(members) == sorted(expected_members), \ (members, expected_members) # There should be no pending members. assert len(group_props['LocalPendingMembers']) == 0, group_props assert len(group_props['RemotePendingMembers']) == 0, group_props # Check that toofer's handle owner is us, and that liz has # no owner. handle_owners = group_props['HandleOwners'] assert handle_owners[toofer] == self_handle, \ (handle_owners, toofer, handle_owners[toofer], self_handle) assert handle_owners[liz] == 0, (handle_owners, liz)
def test_join(q, bus, conn, stream, room_jid, transient_conflict): """ Tells Gabble to join a MUC, but make the first nick it tries conflict with an existing member of the MUC. If transient_conflict is True, then when Gabble successfully joins with a different nick the originally conflicting user turns out not actually to be in the room (they left while we were retrying). """ # Implementation detail: Gabble uses the first part of your jid (if you # don't have an alias) as your room nickname, and appends an underscore a # few times before giving up. member, member_ = [room_jid + '/' + x for x in ['test', 'test_']] call_async(q, conn.Requests, 'CreateChannel', dbus.Dictionary({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room_jid, }, signature='sv')) # Gabble first tries to join as test q.expect('stream-presence', to=member) # MUC says no: there's already someone called test in room_jid presence = elem('presence', from_=member, type='error')( elem(ns.MUC, 'x'), elem('error', type='cancel')( elem(ns.STANZA, 'conflict'), )) stream.send(presence) # Gabble tries again as test_ q.expect('stream-presence', to=member_) # MUC says yes! if not transient_conflict: # Send the other member of the room's presence. This is the nick we # originally wanted. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'test')) # If gabble erroneously thinks the other user's presence is our own, it'll # think that it's got the whole userlist now. If so, syncing here will make # CreateChannel incorrectly return here. sync_stream(q, stream) sync_dbus(bus, q, conn) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'test_')) # Only now should we have finished joining the room. event = q.expect('dbus-return', method='CreateChannel') path, props = event.value text_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') group_props = unwrap(text_chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP)) t, t_ = conn.RequestHandles(cs.HT_CONTACT, [member, member_]) # Check that Gabble think our nickname in the room is test_, not test muc_self_handle = group_props['SelfHandle'] assert muc_self_handle == t_, (muc_self_handle, t_, t) members = group_props['Members'] if transient_conflict: # The user we originally conflicted with isn't actually here; check # there's exactly one member (test_). assert members == [t_], (members, t_, t) else: # Check there are exactly two members (test and test_) assertSameSets([t, t_], members) # In either case, there should be no pending members. assert len(group_props['LocalPendingMembers']) == 0, group_props assert len(group_props['RemotePendingMembers']) == 0, group_props # Check that test_'s handle owner is us, and that test (if it's there) has # no owner. handle_owners = group_props['HandleOwners'] assertEquals (conn.GetSelfHandle(), handle_owners[t_]) if not transient_conflict: assertEquals (0, handle_owners[t]) # test that closing the channel results in an unavailable message to the # right jid text_chan.Close() event = q.expect('stream-presence', to=member_) assertEquals('unavailable', event.stanza['type'])
def test_join(q, bus, conn, stream, room_jid, transient_conflict): """ Tells Gabble to join a MUC, but make the first nick it tries conflict with an existing member of the MUC. If transient_conflict is True, then when Gabble successfully joins with a different nick the originally conflicting user turns out not actually to be in the room (they left while we were retrying). """ # Implementation detail: Gabble uses the first part of your jid (if you # don't have an alias) as your room nickname, and appends an underscore a # few times before giving up. member, member_ = [room_jid + '/' + x for x in ['test', 'test_']] call_async( q, conn.Requests, 'CreateChannel', dbus.Dictionary( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room_jid, }, signature='sv')) # Gabble first tries to join as test q.expect('stream-presence', to=member) # MUC says no: there's already someone called test in room_jid presence = elem('presence', from_=member, type='error')(elem(ns.MUC, 'x'), elem('error', type='cancel')(elem( ns.STANZA, 'conflict'), )) stream.send(presence) # Gabble tries again as test_ q.expect('stream-presence', to=member_) # MUC says yes! if not transient_conflict: # Send the other member of the room's presence. This is the nick we # originally wanted. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'test')) # If gabble erroneously thinks the other user's presence is our own, it'll # think that it's got the whole userlist now. If so, syncing here will make # CreateChannel incorrectly return here. sync_stream(q, stream) sync_dbus(bus, q, conn) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'test_')) # Only now should we have finished joining the room. event = q.expect('dbus-return', method='CreateChannel') path, props = event.value text_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') group_props = unwrap(text_chan.Properties.GetAll(cs.CHANNEL_IFACE_GROUP)) t, t_ = conn.get_contact_handles_sync([member, member_]) # Check that Gabble think our nickname in the room is test_, not test muc_self_handle = group_props['SelfHandle'] assert muc_self_handle == t_, (muc_self_handle, t_, t) members = group_props['Members'] if transient_conflict: # The user we originally conflicted with isn't actually here; check # there's exactly one member (test_). assert members == [t_], (members, t_, t) else: # Check there are exactly two members (test and test_) assertSameSets([t, t_], members) # In either case, there should be no pending members. assert len(group_props['LocalPendingMembers']) == 0, group_props assert len(group_props['RemotePendingMembers']) == 0, group_props # Check that test_'s handle owner is us, and that test (if it's there) has # no owner. handle_owners = group_props['HandleOwners'] assertEquals(conn.Properties.Get(cs.CONN, "SelfHandle"), handle_owners[t_]) if not transient_conflict: assertEquals(0, handle_owners[t]) # test that closing the channel results in an unavailable message to the # right jid text_chan.Close() event = q.expect('stream-presence', to=member_) assertEquals('unavailable', event.stanza['type'])
def test(q, bus, conn, stream): self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") requests = dbus.Interface(conn, CONN_IFACE_REQUESTS) room_jid = '*****@*****.**' call_async( q, requests, 'CreateChannel', dbus.Dictionary( { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, TARGET_HANDLE_TYPE: HT_ROOM, TARGET_ID: room_jid, }, signature='sv')) expected_jid = '%s/%s' % (room_jid, 'test') q.expect('stream-presence', to=expected_jid) # Send presence for another member of the MUC stream.send(make_muc_presence('owner', 'moderator', room_jid, 'liz')) # This is a themed discussion, so the MUC server forces you to have an # appropriate name. self_presence = make_muc_presence('none', 'participant', room_jid, 'toofer') x = [elt for elt in self_presence.elements() if elt.name == 'x'][0] status = x.addElement('status') status['code'] = '110' # "This is you" status = x.addElement('status') status['code'] = '210' # "I renamed you. Muahaha." stream.send(self_presence) # Gabble should figure out from 110 that it's in the room, and from 210 # that we've been renamed. event = q.expect('dbus-return', method='CreateChannel') path, props = event.value text_chan = bus.get_object(conn.bus_name, path) group_props = unwrap( text_chan.GetAll(CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE)) liz, toofer, expected_handle = conn.get_contact_handles_sync( ["%s/%s" % (room_jid, m) for m in ['liz', 'toofer', 'test']]) # Check that Gabble think our nickname in the room is toofer not test muc_self_handle = group_props['SelfHandle'] assert muc_self_handle == toofer, (muc_self_handle, toofer, expected_handle) members = group_props['Members'] # Check there are exactly two members (liz and toofer) expected_members = [liz, toofer] assert sorted(members) == sorted(expected_members), \ (members, expected_members) # There should be no pending members. assert len(group_props['LocalPendingMembers']) == 0, group_props assert len(group_props['RemotePendingMembers']) == 0, group_props # Check that toofer's handle owner is us, and that liz has # no owner. handle_owners = group_props['HandleOwners'] assert handle_owners[toofer] == self_handle, \ (handle_owners, toofer, handle_owners[toofer], self_handle) assert handle_owners[liz] == 0, (handle_owners, liz)
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) announce_socks5_proxy(q, stream, disco_event.stanza) call_async(q, conn, 'RequestHandles', 2, ['*****@*****.**']) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] room_handle = handles[0] # join the muc call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) _, stream_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='[email protected]/test')) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test')) q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(1, [2]) == ['[email protected]/test'] assert conn.InspectHandles(1, [3]) == ['[email protected]/bob'] bob_handle = 3 event = q.expect('dbus-return', method='RequestChannel') # Bob offers a stream tube stream_tube_id = 666 presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'stream' tube['service'] = 'echo' tube['id'] = str(stream_tube_id) parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 's' parameter['type'] = 'str' parameter.addContent('hello') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'ay' parameter['type'] = 'bytes' parameter.addContent('aGVsbG8=') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'u' parameter['type'] = 'uint' parameter.addContent('123') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'i' parameter['type'] = 'int' parameter.addContent('-123') stream.send(presence) # text channel event, new_event = q.expect_many( EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels')) assert event.args[1] == cs.CHANNEL_TYPE_TEXT, event.args channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT # tubes channel is automatically created event, new_event = q.expect_many( EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels')) assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args assert event.args[2] == cs.HT_ROOM assert event.args[3] == room_handle tubes_chan = bus.get_object(conn.bus_name, event.args[0]) tubes_iface = dbus.Interface(tubes_chan, event.args[1]) channel_props = tubes_chan.GetAll(cs.CHANNEL, dbus_interface=cs.PROPERTIES_IFACE) assert channel_props['TargetID'] == '*****@*****.**', channel_props assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == '' assert channel_props['InitiatorHandle'] == 0 channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) q.expect('dbus-signal', signal='NewTube', args=[stream_tube_id, bob_handle, 1, 'echo', sample_parameters, 0]) expected_tube = (stream_tube_id, bob_handle, cs.TUBE_TYPE_STREAM, 'echo', sample_parameters, cs.TUBE_STATE_LOCAL_PENDING) tubes = tubes_iface.ListTubes(byte_arrays=True) assert tubes == [( stream_tube_id, bob_handle, 1, # Stream 'echo', sample_parameters, cs.TUBE_CHANNEL_STATE_LOCAL_PENDING )] assert len(tubes) == 1, unwrap(tubes) t.check_tube_in_tubes(expected_tube, tubes) # tube channel is also announced (new API) new_event = q.expect('dbus-signal', signal='NewChannels') channels = new_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == bob_handle assert props[cs.INITIATOR_ID] == '[email protected]/bob' assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == False assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.STREAM_TUBE_SERVICE] == 'echo' assert props[cs.TUBE_PARAMETERS] == {'s': 'hello', 'ay': 'hello', 'u': 123, 'i': -123} assert access_control in \ props[cs.STREAM_TUBE_SUPPORTED_SOCKET_TYPES][address_type] tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props['Parameters'] == sample_parameters assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING # Accept the tube call_async(q, tubes_iface, 'AcceptStreamTube', stream_tube_id, address_type, access_control, access_control_param, byte_arrays=True) accept_return_event, _ = q.expect_many( EventPattern('dbus-return', method='AcceptStreamTube'), EventPattern('dbus-signal', signal='TubeStateChanged', args=[stream_tube_id, 2])) address = accept_return_event.value[0] socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob', address_type, address, access_control, access_control_param) protocol = socket_event.protocol protocol.sendData("hello initiator") def accept_tube_si_connection(): bytestream, profile = create_from_si_offer(stream, q, bytestream_cls, si_event.stanza, '[email protected]/test') assert profile == ns.TUBES muc_stream_node = xpath.queryForNodes('/iq/si/muc-stream[@xmlns="%s"]' % ns.TUBES, si_event.stanza)[0] assert muc_stream_node is not None assert muc_stream_node['tube'] == str(stream_tube_id) # set the real jid of the target as 'to' because the XMPP server changes # it when delivering the IQ result, si = bytestream.create_si_reply(si_event.stanza, 'test@localhost/Resource') si.addElement((ns.TUBES, 'tube')) stream.send(result) bytestream.wait_bytestream_open() return bytestream bytestream = accept_tube_si_connection() binary = bytestream.get_data() assert binary == 'hello initiator' # reply on the socket bytestream.send_data('hi joiner!') q.expect('socket-data', protocol=protocol, data="hi joiner!") # peer closes the bytestream bytestream.close() e = q.expect('dbus-signal', signal='ConnectionClosed') assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_LOST, e.args[1]) # establish another tube connection socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob', address_type, address, access_control, access_control_param) # bytestream is refused send_error_reply(stream, si_event.stanza) e, _ = q.expect_many( EventPattern('dbus-signal', signal='ConnectionClosed'), EventPattern('socket-disconnected')) assertEquals(conn_id, e.args[0]) assertEquals(cs.CONNECTION_REFUSED, e.args[1]) # establish another tube connection socket_event, si_event, conn_id = t.connect_to_cm_socket(q, '[email protected]/bob', address_type, address, access_control, access_control_param) protocol = socket_event.protocol bytestream = accept_tube_si_connection() # disconnect local socket protocol.transport.loseConnection() e, _ = q.expect_many( EventPattern('dbus-signal', signal='ConnectionClosed'), EventPattern('socket-disconnected')) assertEquals(conn_id, e.args[0]) assertEquals(cs.CANCELLED, e.args[1]) # OK, we're done disconnect_conn(q, conn, stream, [EventPattern('dbus-signal', signal='TubeClosed', args=[stream_tube_id])])
def _start_audio_session(jp, q, bus, conn, stream, incoming): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', '[email protected]/Foo') jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] if incoming: jt.incoming_call() else: ret = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, cs.INITIAL_AUDIO: True }) nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler')) path = nc.args[0] media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # S-E was notified about new session handler, and calls Ready on it session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() nsh_event = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, nsh_event.args[0], 'Media.StreamHandler') group_props = media_chan.GetAll( cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) if incoming: assertEquals([remote_handle], group_props['Members']) assertEquals(unwrap(group_props['LocalPendingMembers']), [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')]) else: assertEquals([self_handle], group_props['Members']) streams = media_chan.ListStreams( dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) stream_id = streams[0][0] stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) msg = u"None of the codecs are good for us, damn!" expected_events = [] if incoming: stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.SupportedCodecs(jt.get_audio_codecs_dbus()) e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) assertEquals(jt.peer, e.query['initiator']) content = xpath.queryForNodes('/iq/jingle/content', e.stanza)[0] assertEquals('initiator', content['creator']) stream.send(make_result_iq(stream, e.stanza)) media_chan.AddMembers([self_handle], 'accepted') memb, acc, _, _, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]), EventPattern('stream-iq', predicate=jp.action_predicate('session-accept')), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), EventPattern('dbus-signal', signal='StreamDirectionChanged', args=[stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0])) stream.send(make_result_iq(stream, acc.stanza)) active_event = jp.rtp_info_event("active") if active_event is not None: q.expect_many(active_event) members = media_chan.GetMembers() assert set(members) == set([self_handle, remote_handle]), members else: stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) session_initiate = q.expect( 'stream-iq', predicate=jp.action_predicate('session-initiate')) q.expect('dbus-signal', signal='MembersChanged', path=path, args=['', [], [], [], [remote_handle], self_handle, cs.GC_REASON_INVITED]) jt.parse_session_initiate(session_initiate.query) stream.send(jp.xml(jp.ResultIq('test@localhost', session_initiate.stanza, []))) jt.accept() q.expect_many( EventPattern('stream-iq', iq_type='result'), # Call accepted EventPattern('dbus-signal', signal='MembersChanged', args=['', [remote_handle], [], [], [], remote_handle, cs.GC_REASON_NONE]), ) return jt, media_iface
def test(q, bus, conn, stream): cm = bus.get_object(cs.CM + '.gabble', tp_path_prefix + '/ConnectionManager/gabble') cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['jabber']), set(protocols.keys())) jabber_props = protocols['jabber'] proto = bus.get_object(cm.bus_name, cm.object_path + '/jabber') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in [ 'Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon' ]: a = jabber_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('*****@*****.**', unwrap(proto_iface.NormalizeContact('[email protected]/Telepathy'))) # Protocol.Interface.Presence expected_status = { 'available': (cs.PRESENCE_AVAILABLE, True, True), 'dnd': (cs.PRESENCE_BUSY, True, True), 'unknown': (cs.PRESENCE_UNKNOWN, False, False), 'away': (cs.PRESENCE_AWAY, True, True), 'xa': (cs.PRESENCE_EXTENDED_AWAY, True, True), 'chat': (cs.PRESENCE_AVAILABLE, True, True), 'error': (cs.PRESENCE_ERROR, False, False), 'offline': (cs.PRESENCE_OFFLINE, False, False), 'testaway': (cs.PRESENCE_AWAY, False, False), 'testbusy': (cs.PRESENCE_BUSY, True, False), 'hidden': (cs.PRESENCE_HIDDEN, True, True) } presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses') # Plugins could add additional statuses, so we check if expected_status is # included in presences rather than equality. for k, v in expected_status.items(): assertEquals(expected_status[k], unwrap(presences[k])) # (Only) 'account' is mandatory for IdentifyAccount() call_async(q, proto_iface, 'IdentifyAccount', {}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = {'account': 'test@localhost'} acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals(test_params['account'], acc_name) assertContains(cs.PROTOCOL_IFACE_AVATARS, proto_props['Interfaces']) avatar_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL_IFACE_AVATARS)) assertEquals(8192, avatar_props['MaximumAvatarBytes']) assertEquals(96, avatar_props['MaximumAvatarHeight']) assertEquals(96, avatar_props['MaximumAvatarWidth']) assertEquals(32, avatar_props['MinimumAvatarHeight']) assertEquals(32, avatar_props['MinimumAvatarWidth']) assertEquals(64, avatar_props['RecommendedAvatarHeight']) assertEquals(64, avatar_props['RecommendedAvatarWidth']) assertEquals(['image/png', 'image/jpeg', 'image/gif'], avatar_props['SupportedAvatarMIMETypes']) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{ 1: (cs.PRESENCE_AVAILABLE, 'available', '') }]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) return
def get_schemes(props): return unwrap (props.Get (cs.ACCOUNT_IFACE_ADDRESSING, 'URISchemes'))
def complete_search(q, bus, conn, stream, server): call_create(q, conn, server) # the channel is not yet in conn.Requests.Channels as it's not ready yet channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE) for path, props in channels: assert props[cs.CHANNEL_TYPE] != cs.CHANNEL_TYPE_CONTACT_SEARCH ret, nc_sig = answer_field_query(q, stream, server) path, props = ret.value props = unwrap(props) expected_search_keys = ['email', 'nickname', 'x-n-family', 'x-n-given'] assert props[cs.CONTACT_SEARCH_SERVER] == server, pformat(props) assert sorted(props[cs.CONTACT_SEARCH_ASK]) == expected_search_keys, \ pformat(props) assert cs.CONTACT_SEARCH_STATE not in props, pformat(props) # check that channel is listed in conn.Requests.Channels channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE) assert (path, props) in channels c = make_channel_proxy(conn, path, 'Channel') c_props = dbus.Interface(c, cs.PROPERTIES_IFACE) c_search = dbus.Interface(c, cs.CHANNEL_TYPE_CONTACT_SEARCH) state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_NOT_STARTED, state # We make a search. iq = make_search(q, c_search, c_props, server, { 'x-n-family': 'Threepwood' }) query = iq.firstChildElement() i = 0 for field in query.elements(): assert field.name == 'last', field.toXml() assert field.children[0] == u'Threepwood', field.children[0] i += 1 assert i == 1, query # Server sends the results of the search. send_results(stream, iq, results.values()) r = q.expect('dbus-signal', signal='SearchResultReceived') infos = r.args[0] assertSameSets(results.keys(), infos.keys()) for id in results.keys(): i = infos[id] r = results[id] i_ = pformat(unwrap(i)) assert ("n", [], [r[2], r[1], "", "", ""]) in i, i_ assert ("nickname", [], [r[3]]) in i, i_ assert ("email", [], [r[0]]) in i, i_ assert ("x-n-family", [], [r[2]]) in i, i_ assert ("x-n-given", [], [r[1]]) in i, i_ assert len(i) == 5, i_ ssc = q.expect('dbus-signal', signal='SearchStateChanged') assert ssc.args[0] == cs.SEARCH_COMPLETED, ssc.args # We call Stop after the search has completed; it should succeed, but leave # the channel in state Completed rather than changing it to Failed for # reason Cancelled. call_async(q, c_search, 'Stop') event = q.expect('dbus-return', method='Stop') state = c_props.Get(cs.CHANNEL_TYPE_CONTACT_SEARCH, 'SearchState') assert state == cs.SEARCH_COMPLETED, (state, cs.SEARCH_COMPLETED) c.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), )
def test(q, bus, conn): cm = bus.get_object(cs.CM + '.salut', tp_path_prefix + '/ConnectionManager/salut') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['local-xmpp']), set(protocols.keys())) local_props = protocols['local-xmpp'] local_params = local_props[cs.PROTOCOL + '.Parameters'] proto = bus.get_object(cm.bus_name, cm.object_path + '/local_xmpp') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('', proto_props['VCardField']) assertEquals('Link-local XMPP', proto_props['EnglishName']) assertEquals('im-local-xmpp', proto_props['Icon']) assertContains(cs.CONN_IFACE_ALIASING, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_AVATARS, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_CONTACTS, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_SIMPLE_PRESENCE, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces']) # local-xmpp has case-sensitive literals as identifiers assertEquals('SMcV@Reptile', unwrap(proto_iface.NormalizeContact('SMcV@Reptile'))) # (Only) 'first-name' and 'last-name' are mandatory for IdentifyAccount() call_async(q, proto_iface, 'IdentifyAccount', {'first-name': 'Simon'}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) # Identifying an account doesn't do much, anyway test_params = {'first-name': 'Simon', 'last-name': 'McVittie'} acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals('', acc_name) assertContains(cs.PROTOCOL_IFACE_AVATARS, proto_props['Interfaces']) avatar_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL_IFACE_AVATARS)) assertEquals(65535, avatar_props['MaximumAvatarBytes']) assertEquals(0, avatar_props['MaximumAvatarHeight']) assertEquals(0, avatar_props['MaximumAvatarWidth']) assertEquals(0, avatar_props['MinimumAvatarHeight']) assertEquals(0, avatar_props['MinimumAvatarWidth']) assertEquals(64, avatar_props['RecommendedAvatarHeight']) assertEquals(64, avatar_props['RecommendedAvatarWidth']) assertEquals(['image/png', 'image/jpeg'], avatar_props['SupportedAvatarMIMETypes']) assertContains(cs.PROTOCOL_IFACE_PRESENCES, proto_props['Interfaces']) expected_status = {'available': (cs.PRESENCE_AVAILABLE, True, True), 'dnd' : (cs.PRESENCE_BUSY, True, True), 'away' : (cs.PRESENCE_AWAY, True, True), 'offline' : (cs.PRESENCE_OFFLINE, False, False)} presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses'); assertEquals(expected_status, presences)
'resource': 'Resource', 'server': 'localhost', 'port': dbus.UInt32(4343), } conn2, jid2 = make_connection(bus, queue.append, params) authenticator = XmppAuthenticator('test2', 'pass') stream2 = make_stream(queue.append, authenticator, protocol=XmppXmlStream) factory = twisted.internet.protocol.Factory() factory.protocol = lambda: stream2 port1 = reactor.listenTCP(4343, factory, interface='localhost') bus.add_signal_receiver( lambda *args, **kw: queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=[unwrap(a) for a in args], interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True) try: test(queue, bus, conn1, conn2, stream1, stream2) finally: try:
'server': 'localhost', 'port': dbus.UInt32(4343), } conn2, jid2 = make_connection(bus, queue.append, params) authenticator = XmppAuthenticator('test2', 'pass') stream2 = make_stream(queue.append, authenticator, protocol=XmppXmlStream) factory = twisted.internet.protocol.Factory() factory.protocol = lambda:stream2 port1 = reactor.listenTCP(4343, factory, interface='localhost') bus.add_signal_receiver( lambda *args, **kw: queue.append(Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True ) try: test(queue, bus, conn1, conn2, stream1, stream2) finally: try:
def test(q, bus, conn, stream, send_early_description_info=False): jp = JingleProtocol031() jt2 = JingleTest2(jp, conn, q, stream, 'test@localhost', '[email protected]/Foo') jt2.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/Foo"])[0] # Remote end calls us jt2.incoming_call() # FIXME: these signals are not observable by real clients, since they # happen before NewChannels. # The caller is in members e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [remote_handle], [], [], [], 0, 0]) # We're pending because of remote_handle e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [], [], [self_handle], [], remote_handle, cs.GC_REASON_INVITED]) chan = wrap_channel(bus.get_object(conn.bus_name, e.path), 'StreamedMedia') # S-E gets notified about new session handler, and calls Ready on it e = q.expect('dbus-signal', signal='NewSessionHandler') assert e.args[1] == 'rtp' if send_early_description_info: """ Regression test for a bug where Gabble would crash if you sent it description-info before calling Ready() on the relevant StreamHandler, and then for a bug where Gabble would never accept the call if a description-info was received before all StreamHandlers were Ready(). """ node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'description-info', [ jp.Content('stream1', 'initiator', 'both', jp.Description('audio', [ ])) ]) ]) stream.send(jp.xml(node)) sync_stream(q, stream) session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() chan.Group.AddMembers([self_handle], 'accepted') # S-E gets notified about a newly-created stream e = q.expect('dbus-signal', signal='NewStreamHandler') id1 = e.args[1] stream_handler = make_channel_proxy(conn, e.args[0], 'Media.StreamHandler') # We are now in members too e = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]) # we are now both in members members = chan.Group.GetMembers() assert set(members) == set([self_handle, remote_handle]), members local_codecs = [('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {'helix':'woo yay'}), ('PCMU', 0, 8000, {}) ] local_codecs_dbus = jt2.dbusify_codecs_with_params(local_codecs) stream_handler.NewNativeCandidate("fake", jt2.get_remote_transports_dbus()) stream_handler.Ready(local_codecs_dbus) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.CodecsUpdated(local_codecs_dbus) local_codecs = [('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {'gstreamer':'rock on'}), ('PCMU', 0, 8000, {}) ] local_codecs_dbus = jt2.dbusify_codecs_with_params(local_codecs) stream_handler.CodecsUpdated(local_codecs_dbus) # First IQ is transport-info; also, we expect to be told what codecs the # other end wants. e, src = q.expect_many( EventPattern('stream-iq', predicate=jp.action_predicate('transport-info')), EventPattern('dbus-signal', signal='SetRemoteCodecs') ) assertEquals('[email protected]/Foo', e.query['initiator']) assert jt2.audio_codecs == [ (name, id, rate, parameters) for id, name, type, rate, channels, parameters in unwrap(src.args[0]) ], \ (jt2.audio_codecs, unwrap(src.args[0])) stream.send(jp.xml(jp.ResultIq('test@localhost', e.stanza, []))) # S-E reports codec intersection, after which gabble can send acceptance stream_handler.SupportedCodecs(local_codecs_dbus) # Second one is session-accept e = q.expect('stream-iq', predicate=jp.action_predicate('session-accept')) # farstream is buggy, and tells tp-fs to tell Gabble to change the third # codec's clockrate. This isn't legal, so Gabble says no. new_codecs = [ ('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {}), ('PCMU', 0, 4000, {}) ] call_async(q, stream_handler, 'CodecsUpdated', jt2.dbusify_codecs(new_codecs)) event = q.expect('dbus-error', method='CodecsUpdated') assert event.error.get_dbus_name() == cs.INVALID_ARGUMENT, \ event.error.get_dbus_name() # With its tail between its legs, tp-fs decides it wants to add some # parameters to the first two codecs, not changing the third. new_codecs = [ ('GSM', 3, 8000, {'type': 'banana'}), ('PCMA', 8, 8000, {'helix': 'BUFFERING'}), ('PCMU', 0, 8000, {}) ] stream_handler.CodecsUpdated(jt2.dbusify_codecs_with_params(new_codecs)) audio_content = jt2.audio_names[0] e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='description-info']", x.stanza)) payload_types = xpath.queryForNodes( "/iq/jingle/content[@name='%s']/description/payload-type" % audio_content, e.stanza) # Gabble SHOULD only include the changed codecs in description-info assert len(payload_types) == 2, payload_types payload_types_tupled = [ (pt['name'], int(pt['id']), int(pt['clockrate']), extract_params(pt)) for pt in payload_types ] assert sorted(payload_types_tupled) == sorted(new_codecs[0:2]), \ (payload_types_tupled, new_codecs[0:2]) # The remote end decides it wants to change the number of channels in the # third codec. This is not meant to happen, so Gabble should send it an IQ # error back. node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'description-info', [ jp.Content(audio_content, 'initiator', 'both', jp.Description('audio', [ jp.PayloadType('PCMU', '1600', '0') ])) ]) ]) stream.send(jp.xml(node)) q.expect('stream-iq', iq_type='error', predicate=lambda x: x.stanza['id'] == node[2]['id']) # Instead, the remote end decides to add a parameter to the third codec. new_codecs = [ ('GSM', 3, 8000, {}), ('PCMA', 8, 8000, {}), ('PCMU', 0, 8000, {'choppy': 'false'}), ] # As per the XEP, it only sends the ones which have changed. c = new_codecs[2] node = jp.SetIq(jt2.peer, jt2.jid, [ jp.Jingle(jt2.sid, jt2.peer, 'description-info', [ jp.Content(audio_content, 'initiator', 'both', jp.Description('audio', [ jp.PayloadType(c[0], str(c[2]), str(c[1]), c[3]) ])) ]) ]) stream.send(jp.xml(node)) # Gabble should patch its idea of the remote codecs with the update it just # got, and emit SetRemoteCodecs for them all. e = q.expect('dbus-signal', signal='SetRemoteCodecs') new_codecs_dbus = unwrap(jt2.dbusify_codecs_with_params(new_codecs)) announced = unwrap(e.args[0]) assert new_codecs_dbus == announced, (new_codecs_dbus, announced) # We close the session by removing the stream chan.StreamedMedia.RemoveStreams([id1]) e = q.expect('stream-iq', iq_type='set', predicate=lambda x: xpath.queryForNodes("/iq/jingle[@action='session-terminate']", x.stanza))
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return conn.Connect() _, iq_event = q.expect_many( EventPattern("dbus-signal", signal="StatusChanged", args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern("stream-iq", to=None, query_ns="vcard-temp", query_name="vCard"), ) acknowledge_iq(stream, iq_event.stanza) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0] t.check_conn_properties(q, conn) room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, "*****@*****.**") tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) bob_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/bob"])[0] address = t.create_server(q, address_type) # offer stream tube (old API) using an Unix socket call_async( q, tubes_iface, "OfferStreamTube", "echo", sample_parameters, address_type, address, access_control, access_control_param, ) new_tube_event, stream_event, _, new_channels_event = q.expect_many( EventPattern("dbus-signal", signal="NewTube"), EventPattern("stream-presence", to="[email protected]/test"), EventPattern("dbus-return", method="OfferStreamTube"), EventPattern("dbus-signal", signal="NewChannels"), ) # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[1] == tubes_self_handle assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == "echo" assert new_tube_event.args[4] == sample_parameters assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN # handle stream_event # We announce our newly created tube in our muc presence presence = stream_event.stanza x_nodes = xpath.queryForNodes('/presence/x[@xmlns="http://jabber.org/' 'protocol/muc"]', presence) assert x_nodes is not None assert len(x_nodes) == 1 tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes("/tubes/tube", tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube["type"] == "stream" assert not tube.hasAttribute("initiator") assert tube["service"] == "echo" assert not tube.hasAttribute("stream-id") assert not tube.hasAttribute("dbus-name") assert tube["id"] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes("/tube/parameters/parameter", tube) for node in parameter_nodes: assert node["name"] not in params params[node["name"]] = (node["type"], str(node)) assert params == {"ay": ("bytes", "aGVsbG8="), "s": ("str", "hello"), "i": ("int", "-123"), "u": ("uint", "123")} # tube is also announced using new API channels = new_channels_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == tubes_self_handle assert props[cs.INITIATOR_ID] == "[email protected]/test" assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == True assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == "*****@*****.**" assert props[cs.STREAM_TUBE_SERVICE] == "echo" tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props["Parameters"] == sample_parameters assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_OPEN tubes = tubes_iface.ListTubes(byte_arrays=True) assert tubes == [ (stream_tube_id, tubes_self_handle, 1, "echo", sample_parameters, cs.TUBE_CHANNEL_STATE_OPEN) # Stream ] assert len(tubes) == 1, unwrap(tubes) expected_tube = ( stream_tube_id, tubes_self_handle, cs.TUBE_TYPE_STREAM, "echo", sample_parameters, cs.TUBE_STATE_OPEN, ) t.check_tube_in_tubes(expected_tube, tubes) # FIXME: if we use an unknown JID here, everything fails # (the code uses lookup where it should use ensure) bytestream = connect_to_tube(stream, q, bytestream_cls, "*****@*****.**", stream_tube_id) iq_event, socket_event, _, conn_event = q.expect_many( EventPattern("stream-iq", iq_type="result"), EventPattern("socket-connected"), EventPattern( "dbus-signal", signal="StreamTubeNewConnection", args=[stream_tube_id, bob_handle], interface=cs.CHANNEL_TYPE_TUBES, ), EventPattern("dbus-signal", signal="NewRemoteConnection", interface=cs.CHANNEL_TYPE_STREAM_TUBE), ) protocol = socket_event.protocol # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 handle, access, conn_id = conn_event.args assert handle == bob_handle use_tube(q, bytestream, protocol, conn_id) # offer a stream tube to another room (new API) address = t.create_server(q, address_type, block_reading=True) request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: "*****@*****.**", cs.STREAM_TUBE_SERVICE: "newecho", } _, _, new_tube_path, new_tube_props = join_muc(q, bus, conn, stream, "*****@*****.**", request) # first text and tubes channels are announced event = q.expect("dbus-signal", signal="NewChannels") channels = event.args[0] assert len(channels) == 2 path1, prop1 = channels[0] path2, prop2 = channels[1] assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES] got_text, got_tubes = False, False for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT: got_text = True elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES: got_tubes = True else: assert False assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == self_name assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES] assert props[cs.TARGET_ID] == "*****@*****.**" assert props[cs.REQUESTED] == False assert (got_text, got_tubes) == (True, True) # now the tube channel is announced # FIXME: in this case, all channels should probably be announced together event = q.expect("dbus-signal", signal="NewChannels") channels = event.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert prop[cs.INITIATOR_ID] == "[email protected]/test" assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == "*****@*****.**" assert prop[cs.STREAM_TUBE_SERVICE] == "newecho" # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, "Channels", dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert tube_props["State"] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # offer the tube call_async(q, stream_tube_iface, "Offer", address_type, address, access_control, {"foo": "bar"}) new_tube_event, stream_event, _, status_event = q.expect_many( EventPattern("dbus-signal", signal="NewTube"), EventPattern("stream-presence", to="[email protected]/test"), EventPattern("dbus-return", method="Offer"), EventPattern("dbus-signal", signal="TubeChannelStateChanged", args=[cs.TUBE_CHANNEL_STATE_OPEN]), ) tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ["[email protected]/test"] # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == "newecho" assert new_tube_event.args[4] == {"foo": "bar"} assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN presence = stream_event.stanza x_nodes = xpath.queryForNodes('/presence/x[@xmlns="http://jabber.org/' 'protocol/muc"]', presence) assert x_nodes is not None assert len(x_nodes) == 1 tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes("/tubes/tube", tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube["type"] == "stream" assert not tube.hasAttribute("initiator") assert tube["service"] == "newecho" assert not tube.hasAttribute("stream-id") assert not tube.hasAttribute("dbus-name") assert tube["id"] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes("/tube/parameters/parameter", tube) for node in parameter_nodes: assert node["name"] not in params params[node["name"]] = (node["type"], str(node)) assert params == {"foo": ("str", "bar")} bob_handle = conn.RequestHandles(cs.HT_CONTACT, ["[email protected]/bob"])[0] bytestream = connect_to_tube(stream, q, bytestream_cls, "*****@*****.**", stream_tube_id) iq_event, socket_event, conn_event = q.expect_many( EventPattern("stream-iq", iq_type="result"), EventPattern("socket-connected"), EventPattern("dbus-signal", signal="NewRemoteConnection", interface=cs.CHANNEL_TYPE_STREAM_TUBE), ) handle, access, conn_id = conn_event.args assert handle == bob_handle protocol = socket_event.protocol # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 use_tube(q, bytestream, protocol, conn_id) chan_iface.Close() q.expect_many(EventPattern("dbus-signal", signal="Closed"), EventPattern("dbus-signal", signal="ChannelClosed"))
def test(q, bus, conn, sip): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) self_handle = conn.Get(cs.CONN, 'SelfHandle', dbus_interface=cs.PROPERTIES_IFACE) self_uri = conn.inspect_contact_sync(self_handle) contact = 'sip:[email protected]' handle = conn.get_contact_handle_sync(contact) chan, _ = conn.Requests.CreateChannel({ cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: handle }) requested_obj, target_handle = test_new_channel(q, bus, conn, target_uri=contact, initiator_uri=self_uri, requested=True) assert requested_obj.object_path == chan, requested_obj.object_path assert target_handle == handle, (target_handle, handle) iface = dbus.Interface(requested_obj, cs.CHANNEL_TYPE_TEXT) iface.Send(0, 'Hello') event = q.expect('sip-message', uri='sip:[email protected]', body='Hello') sip.deliverResponse(sip.responseFromRequest(404, event.sip_message)) q.expect('dbus-signal', signal='SendError') iface.Send(0, 'Hello Again') event = q.expect('sip-message', uri='sip:[email protected]', body='Hello Again') sip.deliverResponse(sip.responseFromRequest(200, event.sip_message)) ua_via = twisted.protocols.sip.parseViaHeader(event.headers['via'][0]) conn.ReleaseHandles(1, [handle]) call_id = 'XYZ@localhost' send_message(sip, ua_via, 'Hi', call_id=call_id, time=1234567890) incoming_obj, handle = test_new_channel(q, bus, conn, target_uri=FROM_URL, initiator_uri=FROM_URL, requested=False) iface = dbus.Interface(incoming_obj, cs.CHANNEL_TYPE_TEXT) name = conn.inspect_contact_sync(handle) assert name == FROM_URL event = q.expect('dbus-signal', signal='MessageReceived') msg = event.args[0] now = time.time() assert msg[0]['message-token'] == "%s;cseq=%u" % (call_id, cseq_num) assert now - 10 < msg[0]['message-received'] < now + 10 assert msg[0]['message-sent'] == 1234567890 assert msg[1]['content-type'] == 'text/plain' assert msg[1]['content'] == 'Hi' # FIXME: times out for some reason, the response is in fact sent; # race condition with the earlier wait for 'dbus-signal'? #event = q.expect('sip-response', code=200) iface.AcknowledgePendingMessages([msg[0]['pending-message-id']]) # Test conversion from an 8-bit encoding. # Due to limited set of encodings available in some environments, # try with US ASCII and ISO 8859-1. send_message(sip, ua_via, u'straight ASCII'.encode('us-ascii'), encoding='us-ascii') event = q.expect('dbus-signal', signal='Received') assert event.args[5] == 'straight ASCII' iface.AcknowledgePendingMessages([event.args[0]]) send_message(sip, ua_via, u'Hyv\xe4!'.encode('iso-8859-1'), encoding='iso-8859-1') event = q.expect('dbus-signal', signal='Received') assert event.args[5] == u'Hyv\xe4!' conn.ReleaseHandles(1, [handle]) iface = dbus.Interface(incoming_obj, cs.CHANNEL_IFACE_DESTROYABLE) iface.Destroy() del iface event = q.expect('dbus-signal', signal='Closed') del incoming_obj # Sending the message to appear on the requested channel pending_msgs = [] send_message(sip, ua_via, 'How are you doing now, old pal?', sender=contact) event = q.expect('dbus-signal', signal='Received', path=chan) assert event.args[5] == 'How are you doing now, old pal?' pending_msgs.append(tuple(event.args)) send_message(sip, ua_via, 'I hope you can receive it', sender=contact) event = q.expect('dbus-signal', signal='Received') assert event.args[5] == 'I hope you can receive it' pending_msgs.append(tuple(event.args)) # Don't acknowledge the last messages, close the channel so that it's reopened dbus.Interface(requested_obj, cs.CHANNEL).Close() del requested_obj event = q.expect('dbus-signal', signal='Closed', path=chan) requested_obj, handle = test_new_channel(q, bus, conn, target_uri=contact, initiator_uri=contact, requested=False) # Expect Channel_Text_Message_Flag_Resqued to be set pending_msgs = [message_with_resqued(msg) for msg in pending_msgs] # The first message is the delivery report of the message we failed to # send so we'll skip it. iface = dbus.Interface(requested_obj, cs.CHANNEL_TYPE_TEXT) pending_res = iface.ListPendingMessages(False) assert pending_msgs == pending_res[1:], (pending_msgs, unwrap(pending_res)[1:]) pending_res = iface.ListPendingMessages(True) assert pending_msgs == pending_res[1:], (pending_msgs, unwrap(pending_res)[1:]) # There should be no pending messages any more pending_res = iface.ListPendingMessages(False) assert pending_res == [], pending_res del iface # Hit also the code path for closing the channel with no pending messages dbus.Interface(requested_obj, cs.CHANNEL).Close() event = q.expect('dbus-signal', signal='Closed') del requested_obj # Hit the message zapping path when the connection is disconnected send_message(sip, ua_via, 'Will you leave this unacknowledged?') test_new_channel(q, bus, conn, target_uri=FROM_URL, initiator_uri=FROM_URL, requested=False) conn.Disconnect() # Check the last channel with an unacknowledged message event = q.expect('dbus-signal', signal='Closed') q.expect('dbus-signal', signal='StatusChanged', args=[2, 1])
'resource': 'Resource', 'server': 'localhost', 'port': dbus.UInt32(4343), } conn2, jid2 = make_connection(bus, queue.append, params) authenticator = XmppAuthenticator('test2', 'pass') stream2 = make_stream(queue.append, authenticator, protocol=XmppXmlStream) factory = twisted.internet.protocol.Factory() factory.protocol = lambda: stream2 port1 = reactor.listenTCP(4343, factory, interface='localhost') bus.add_signal_receiver( lambda *args, **kw: queue.append( Event('dbus-signal', path=unwrap(kw['path']), signal=kw['member'], args=map(unwrap, args), interface=kw['interface'])), None, # signal name None, # interface None, path_keyword='path', member_keyword='member', interface_keyword='interface', byte_arrays=True) try: test(queue, bus, conn1, conn2, stream1, stream2) finally: try:
def test(q, bus, conn, stream): cm = bus.get_object(cs.CM + '.gabble', tp_path_prefix + '/ConnectionManager/gabble') cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['jabber']), set(protocols.keys())) jabber_props = protocols['jabber'] proto = bus.get_object(cm.bus_name, cm.object_path + '/jabber') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in ['Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon']: a = jabber_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('*****@*****.**', unwrap(proto_iface.NormalizeContact('[email protected]/Telepathy'))) # Protocol.Interface.Presence expected_status = {'available': (cs.PRESENCE_AVAILABLE, True, True), 'dnd' : (cs.PRESENCE_BUSY, True, True), 'unknown' : (cs.PRESENCE_UNKNOWN, False, False), 'away' : (cs.PRESENCE_AWAY, True, True), 'xa' : (cs.PRESENCE_EXTENDED_AWAY, True, True), 'chat' : (cs.PRESENCE_AVAILABLE, True, True), 'error' : (cs.PRESENCE_ERROR, False, False), 'offline' : (cs.PRESENCE_OFFLINE, False, False), 'testaway' : (cs.PRESENCE_AWAY, False, False), 'testbusy' : (cs.PRESENCE_BUSY, True, False), 'hidden' : (cs.PRESENCE_HIDDEN, True, True)} presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses'); # Plugins could add additional statuses, so we check if expected_status is # included in presences rather than equality. for k, v in expected_status.iteritems(): assertEquals(expected_status[k], unwrap(presences[k])) # (Only) 'account' is mandatory for IdentifyAccount() call_async(q, proto_iface, 'IdentifyAccount', {}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) test_params = { 'account': 'test@localhost' } acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals(test_params['account'], acc_name) assertContains(cs.PROTOCOL_IFACE_AVATARS, proto_props['Interfaces']) avatar_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL_IFACE_AVATARS)) assertEquals(8192, avatar_props['MaximumAvatarBytes']) assertEquals(96, avatar_props['MaximumAvatarHeight']) assertEquals(96, avatar_props['MaximumAvatarWidth']) assertEquals(32, avatar_props['MinimumAvatarHeight']) assertEquals(32, avatar_props['MinimumAvatarWidth']) assertEquals(64, avatar_props['RecommendedAvatarHeight']) assertEquals(64, avatar_props['RecommendedAvatarWidth']) assertEquals(['image/png', 'image/jpeg', 'image/gif'], avatar_props['SupportedAvatarMIMETypes']) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED]) q.expect('stream-authenticated') q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_AVAILABLE, 'available', '')}])
def test(q, bus, conn, stream): conn.Connect() properties = conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) assert properties.get('Channels') == [], properties['Channels'] assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE] ) in properties.get('RequestableChannelClasses'),\ unwrap(properties['RequestableChannelClasses']) _, vcard_event, roster_event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) acknowledge_iq(stream, vcard_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' item['subscription'] = 'both' stream.send(roster) presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@localhost/Bob' presence['to'] = 'test@localhost/Resource' c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to='bob@localhost/Bob') result = event.stanza result['type'] = 'result' assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' feature = event.query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) bob_handle = conn.get_contact_handle_sync('bob@localhost') def new_chan_predicate(e): types = [] for _, props in e.args[0]: types.append(props[cs.CHANNEL_TYPE]) return cs.CHANNEL_TYPE_STREAM_TUBE in types call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: 'the.service', }) ret, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) chan_path, props = ret.value # Ensure a tube to the same person; check it's the same one. # call_async(q, conn.Requests, 'EnsureChannel', # { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, # cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, # cs.TARGET_HANDLE: bob_handle, # cs.STREAM_TUBE_SERVICE: 'the.service', # }) # ret = q.expect('dbus-return', method='EnsureChannel') # yours, ensured_path, _ = ret.value # assert ensured_path == chan_path, (ensured_path, chan_path) # assert not yours chan = bus.get_object(conn.bus_name, chan_path) chan.Close() # Now let's try ensuring a new tube. call_async( q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: 'the.service', }) ret, new_sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) yours, path, props = ret.value assert yours emitted_props = new_sig.args[0][0][1] assert props == emitted_props, (props, emitted_props) chan = bus.get_object(conn.bus_name, path) chan.Close()
def test(q, bus, conn, stream, bytestream_cls, address_type, access_control, access_control_param): if bytestream_cls in [BytestreamS5BRelay, BytestreamS5BRelayBugged]: # disable SOCKS5 relay tests because proxy can't be used with muc # contacts atm return iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) self_handle = conn.GetSelfHandle() self_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0] t.check_conn_properties(q, conn) room_handle, tubes_chan, tubes_iface = get_muc_tubes_channel(q, bus, conn, stream, '*****@*****.**') tubes_self_handle = tubes_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['[email protected]/bob'])[0] address = t.create_server(q, address_type) # offer stream tube (old API) using an Unix socket call_async(q, tubes_iface, 'OfferStreamTube', 'echo', sample_parameters, address_type, address, access_control, access_control_param) new_tube_event, stream_event, _, new_channels_event = q.expect_many( EventPattern('dbus-signal', signal='NewTube'), EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-return', method='OfferStreamTube'), EventPattern('dbus-signal', signal='NewChannels')) # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[1] == tubes_self_handle assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == 'echo' assert new_tube_event.args[4] == sample_parameters assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN # handle stream_event # We announce our newly created tube in our muc presence presence = stream_event.stanza tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') assert tube['service'] == 'echo' assert not tube.hasAttribute('stream-id') assert not tube.hasAttribute('dbus-name') assert tube['id'] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'ay': ('bytes', 'aGVsbG8='), 's': ('str', 'hello'), 'i': ('int', '-123'), 'u': ('uint', '123'), } # tube is also announced using new API channels = new_channels_event.args[0] assert len(channels) == 1 path, props = channels[0] assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert props[cs.INITIATOR_HANDLE] == tubes_self_handle assert props[cs.INITIATOR_ID] == '[email protected]/test' assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP, cs.CHANNEL_IFACE_TUBE] assert props[cs.REQUESTED] == True assert props[cs.TARGET_HANDLE] == room_handle assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.STREAM_TUBE_SERVICE] == 'echo' tube_chan = bus.get_object(conn.bus_name, path) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assert tube_props['Parameters'] == sample_parameters assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_OPEN tubes = tubes_iface.ListTubes(byte_arrays=True) assert tubes == [( stream_tube_id, tubes_self_handle, 1, # Stream 'echo', sample_parameters, cs.TUBE_CHANNEL_STATE_OPEN )] assert len(tubes) == 1, unwrap(tubes) expected_tube = (stream_tube_id, tubes_self_handle, cs.TUBE_TYPE_STREAM, 'echo', sample_parameters, cs.TUBE_STATE_OPEN) t.check_tube_in_tubes(expected_tube, tubes) # FIXME: if we use an unknown JID here, everything fails # (the code uses lookup where it should use ensure) bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id) iq_event, socket_event, _, conn_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('socket-connected'), EventPattern('dbus-signal', signal='StreamTubeNewConnection', args=[stream_tube_id, bob_handle], interface=cs.CHANNEL_TYPE_TUBES), EventPattern('dbus-signal', signal='NewRemoteConnection', interface=cs.CHANNEL_TYPE_STREAM_TUBE)) protocol = socket_event.protocol # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 handle, access, conn_id = conn_event.args assert handle == bob_handle use_tube(q, bytestream, protocol, conn_id) # offer a stream tube to another room (new API) address = t.create_server(q, address_type, block_reading=True) request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**', cs.STREAM_TUBE_SERVICE: 'newecho', } _, _, new_tube_path, new_tube_props = \ join_muc(q, bus, conn, stream, '*****@*****.**', request) # The order in which the NewChannels signals are fired is # undefined -- it could be the (tubes, text) channels first, or it # could be the tube channel first; so let's accept either order # here. first, second = q.expect_many( EventPattern('dbus-signal', signal='NewChannels'), EventPattern('dbus-signal', signal='NewChannels')) # NewChannels signal with the text and tubes channels together. def nc_textandtubes(event): channels = event.args[0] assert len(channels) == 2 path1, prop1 = channels[0] path2, prop2 = channels[1] assert sorted([prop1[cs.CHANNEL_TYPE], prop2[cs.CHANNEL_TYPE]]) == \ [cs.CHANNEL_TYPE_TEXT, cs.CHANNEL_TYPE_TUBES] got_text, got_tubes = False, False for path, props in channels: if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT: got_text = True elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES: got_tubes = True else: assert False assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == self_name assert cs.CHANNEL_IFACE_GROUP in props[cs.INTERFACES] assert props[cs.TARGET_ID] == '*****@*****.**' assert props[cs.REQUESTED] == False assert (got_text, got_tubes) == (True, True) # NewChannels signal with the tube channel. def nc_tube(event): # FIXME: in this case, all channels should probably be announced together channels = event.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE assert prop[cs.INITIATOR_ID] == '[email protected]/test' assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == '*****@*****.**' assert prop[cs.STREAM_TUBE_SERVICE] == 'newecho' return path, prop if len(first.args[0]) == 1: path, prop = nc_tube(first) nc_textandtubes(second) else: nc_textandtubes(first) path, prop = nc_tube(second) # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = bus.get_object(conn.bus_name, path) stream_tube_iface = dbus.Interface(tube_chan, cs.CHANNEL_TYPE_STREAM_TUBE) chan_iface = dbus.Interface(tube_chan, cs.CHANNEL) tube_props = tube_chan.GetAll(cs.CHANNEL_IFACE_TUBE, dbus_interface=cs.PROPERTIES_IFACE) assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # offer the tube call_async(q, stream_tube_iface, 'Offer', address_type, address, access_control, {'foo': 'bar'}) new_tube_event, stream_event, _, status_event = q.expect_many( EventPattern('dbus-signal', signal='NewTube'), EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-return', method='Offer'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN])) tube_self_handle = tube_chan.GetSelfHandle(dbus_interface=cs.CHANNEL_IFACE_GROUP) assert conn.InspectHandles(cs.HT_CONTACT, [tube_self_handle]) == ['[email protected]/test'] # handle new_tube_event stream_tube_id = new_tube_event.args[0] assert new_tube_event.args[2] == 1 # Stream assert new_tube_event.args[3] == 'newecho' assert new_tube_event.args[4] == {'foo': 'bar'} assert new_tube_event.args[5] == cs.TUBE_CHANNEL_STATE_OPEN presence = stream_event.stanza tubes_nodes = xpath.queryForNodes('/presence/tubes[@xmlns="%s"]' % ns.TUBES, presence) assert tubes_nodes is not None assert len(tubes_nodes) == 1 tube_nodes = xpath.queryForNodes('/tubes/tube', tubes_nodes[0]) assert tube_nodes is not None assert len(tube_nodes) == 1 for tube in tube_nodes: assert tube['type'] == 'stream' assert not tube.hasAttribute('initiator') assert tube['service'] == 'newecho' assert not tube.hasAttribute('stream-id') assert not tube.hasAttribute('dbus-name') assert tube['id'] == str(stream_tube_id) params = {} parameter_nodes = xpath.queryForNodes('/tube/parameters/parameter', tube) for node in parameter_nodes: assert node['name'] not in params params[node['name']] = (node['type'], str(node)) assert params == {'foo': ('str', 'bar')} bob_handle = conn.RequestHandles(cs.HT_CONTACT, ['[email protected]/bob'])[0] bytestream = connect_to_tube(stream, q, bytestream_cls, '*****@*****.**', stream_tube_id) iq_event, socket_event, conn_event = q.expect_many( EventPattern('stream-iq', iq_type='result'), EventPattern('socket-connected'), EventPattern('dbus-signal', signal='NewRemoteConnection', interface=cs.CHANNEL_TYPE_STREAM_TUBE)) handle, access, conn_id = conn_event.args assert handle == bob_handle protocol = socket_event.protocol # start to read from the transport so we can read the control byte protocol.transport.startReading() t.check_new_connection_access(q, access_control, access, protocol) # handle iq_event bytestream.check_si_reply(iq_event.stanza) tube = xpath.queryForNodes('/iq//si/tube[@xmlns="%s"]' % ns.TUBES, iq_event.stanza) assert len(tube) == 1 use_tube(q, bytestream, protocol, conn_id) chan_iface.Close() q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'))
def test(jp, q, bus, conn, stream, peer='[email protected]/Foo'): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', peer) jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] # Remote end calls us jt.incoming_call() # If this is a Jingle dialect that supports it, Gabble should send a # <ringing/> notification when it gets the session-initiate until Telepathy # has a way for the UI to do this. # https://bugs.freedesktop.org/show_bug.cgi?id=21964 ringing_event = jp.rtp_info_event_list("ringing") if jp.dialect == 'gtalk-v0.4': # With gtalk4, apparently we have to send transport-accept immediately, # not even just before we send our transport-info. wjt tested this, and # indeed if we don't send this for incoming calls, the call never # connects. ta_event = [ EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/session[@type='transport-accept']", x.stanza)), ] else: ta_event = [] nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler'), *(ringing_event + ta_event) )[0:2] path, ct, ht, h, _ = nc.args assert ct == cs.CHANNEL_TYPE_STREAMED_MEDIA, ct assert ht == cs.HT_CONTACT, ht assert h == remote_handle, h media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # S-E was notified about new session handler, and calls Ready on it assert e.args[1] == 'rtp' session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() nsh_event = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, nsh_event.args[0], 'Media.StreamHandler') streams = media_iface.ListStreams() assertLength(1, streams) stream_id, stream_handle, stream_type, _, stream_direction, pending_flags =\ streams[0] assertEquals(remote_handle, stream_handle) assertEquals(cs.MEDIA_STREAM_TYPE_AUDIO, stream_type) assertEquals(cs.MEDIA_STREAM_DIRECTION_RECEIVE, stream_direction) assertEquals(cs.MEDIA_STREAM_PENDING_LOCAL_SEND, pending_flags) # Exercise channel properties channel_props = media_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(remote_handle, channel_props['TargetHandle']) assertEquals(cs.HT_CONTACT, channel_props['TargetHandleType']) assertEquals((cs.HT_CONTACT, remote_handle), media_chan.GetHandle(dbus_interface=cs.CHANNEL)) assertEquals(jt.peer_bare_jid, channel_props['TargetID']) assertEquals(jt.peer_bare_jid, channel_props['InitiatorID']) assertEquals(remote_handle, channel_props['InitiatorHandle']) assertEquals(False, channel_props['Requested']) group_props = media_chan.GetAll( cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) assert group_props['SelfHandle'] == self_handle, \ (group_props['SelfHandle'], self_handle) flags = group_props['GroupFlags'] assert flags & cs.GF_PROPERTIES, flags # Changing members in any way other than adding or removing yourself is # meaningless for incoming calls, and the flags need not be sent to change # your own membership. assert not flags & cs.GF_CAN_ADD, flags assert not flags & cs.GF_CAN_REMOVE, flags assert not flags & cs.GF_CAN_RESCIND, flags assert group_props['Members'] == [remote_handle], group_props['Members'] assert group_props['RemotePendingMembers'] == [], \ group_props['RemotePendingMembers'] # We're local pending because remote_handle invited us. assert group_props['LocalPendingMembers'] == \ [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')], \ unwrap(group_props['LocalPendingMembers']) streams = media_chan.ListStreams( dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) assert len(streams) == 1, streams assert len(streams[0]) == 6, streams[0] # streams[0][0] is the stream identifier, which in principle we can't # make any assertion about (although in practice it's probably 1) assert streams[0][1] == remote_handle, (streams[0], remote_handle) assert streams[0][2] == cs.MEDIA_STREAM_TYPE_AUDIO, streams[0] # We haven't connected yet assert streams[0][3] == cs.MEDIA_STREAM_STATE_DISCONNECTED, streams[0] # In Gabble, incoming streams start off with remote send enabled, and # local send requested assert streams[0][4] == cs.MEDIA_STREAM_DIRECTION_RECEIVE, streams[0] assert streams[0][5] == cs.MEDIA_STREAM_PENDING_LOCAL_SEND, streams[0] # Connectivity checks happen before we have accepted the call stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.get_audio_codecs_dbus()) stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) stream_handler.SupportedCodecs(jt.get_audio_codecs_dbus()) # peer gets the transport e = q.expect('stream-iq', predicate=jp.action_predicate('transport-info')) assertEquals(jt.peer, e.query['initiator']) if jp.dialect in ['jingle-v0.15', 'jingle-v0.31']: content = xpath.queryForNodes('/iq/jingle/content', e.stanza)[0] assertEquals('initiator', content['creator']) stream.send(make_result_iq(stream, e.stanza)) # At last, accept the call media_chan.AddMembers([self_handle], 'accepted') # Call is accepted, we become a member, and the stream that was pending # local send is now sending. memb, acc, _, _, _ = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [self_handle], [], [], [], self_handle, cs.GC_REASON_NONE]), EventPattern('stream-iq', predicate=jp.action_predicate('session-accept')), EventPattern('dbus-signal', signal='SetStreamSending', args=[True]), EventPattern('dbus-signal', signal='SetStreamPlaying', args=[True]), EventPattern('dbus-signal', signal='StreamDirectionChanged', args=[stream_id, cs.MEDIA_STREAM_DIRECTION_BIDIRECTIONAL, 0]), ) stream.send(make_result_iq(stream, acc.stanza)) # Also, if this is a Jingle dialect that supports it, Gabble should send an # <active/> notification when the session-accept is acked (until the # Telepathy spec lets the UI say it's not ringing any more). active_event = jp.rtp_info_event("active") if active_event is not None: q.expect_many(active_event) # we are now both in members members = media_chan.GetMembers() assert set(members) == set([self_handle, remote_handle]), members # Connected! Blah, blah, ... # 'Nuff said jt.terminate() q.expect('dbus-signal', signal='Closed', path=path)
def _test_terminate_reason(jp, q, bus, conn, stream, incoming): jt = JingleTest2(jp, conn, q, stream, 'test@localhost', '[email protected]/Foo') jt.prepare() self_handle = conn.GetSelfHandle() remote_handle = conn.RequestHandles(cs.HT_CONTACT, [jt.peer])[0] if incoming: jt.incoming_call() else: ret = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAMED_MEDIA, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: remote_handle, cs.INITIAL_AUDIO: True }) nc, e = q.expect_many( EventPattern('dbus-signal', signal='NewChannel', predicate=lambda e: cs.CHANNEL_TYPE_CONTACT_LIST not in e.args), EventPattern('dbus-signal', signal='NewSessionHandler')) path = nc.args[0] media_chan = make_channel_proxy(conn, path, 'Channel.Interface.Group') media_iface = make_channel_proxy(conn, path, 'Channel.Type.StreamedMedia') # S-E was notified about new session handler, and calls Ready on it session_handler = make_channel_proxy(conn, e.args[0], 'Media.SessionHandler') session_handler.Ready() nsh_event = q.expect('dbus-signal', signal='NewStreamHandler') # S-E gets notified about a newly-created stream stream_handler = make_channel_proxy(conn, nsh_event.args[0], 'Media.StreamHandler') group_props = media_chan.GetAll( cs.CHANNEL_IFACE_GROUP, dbus_interface=dbus.PROPERTIES_IFACE) if incoming: assertEquals([remote_handle], group_props['Members']) assertEquals(unwrap(group_props['LocalPendingMembers']), [(self_handle, remote_handle, cs.GC_REASON_INVITED, '')]) else: assertEquals([self_handle], group_props['Members']) streams = media_chan.ListStreams( dbus_interface=cs.CHANNEL_TYPE_STREAMED_MEDIA) stream_id = streams[0][0] stream_handler.NewNativeCandidate("fake", jt.get_remote_transports_dbus()) stream_handler.Ready(jt.dbusify_codecs([("FOO", 5, 8000, {})])) msg = u"None of the codecs are good for us, damn!" expected_events = [] if incoming: q.expect('dbus-signal', signal='SetRemoteCodecs') stream_handler.Error(cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, msg) expected_events = [EventPattern( "stream-iq", iq_type="set", predicate=lambda x: _session_terminate_predicate(x, msg))] rejector = self_handle else: stream_handler.StreamState(cs.MEDIA_STREAM_STATE_CONNECTED) session_initiate = q.expect( 'stream-iq', predicate=jp.action_predicate('session-initiate')) q.expect('dbus-signal', signal='MembersChanged', path=path, args=['', [], [], [], [remote_handle], self_handle, cs.GC_REASON_INVITED]) jt.parse_session_initiate(session_initiate.query) stream.send(jp.xml(jp.ResultIq('test@localhost', session_initiate.stanza, []))) jt.terminate('failed-application', msg) rejector = remote_handle expected_events += [ EventPattern('dbus-signal', signal='StreamError', interface=cs.CHANNEL_TYPE_STREAMED_MEDIA, path=path, args=[stream_id, cs.MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED, msg]), EventPattern('dbus-signal', signal='MembersChanged', interface=cs.CHANNEL_IFACE_GROUP, path=path, args=[msg, [], [self_handle, remote_handle], [], [], rejector, cs.GC_REASON_ERROR])] q.expect_many(*expected_events) q.expect('dbus-signal', signal='Closed', path=path)
def test(q, bus, conn, stream): conn.Connect() _, iq_event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) acknowledge_iq(stream, iq_event.stanza) call_async(q, conn, 'RequestHandles', cs.HT_ROOM, ['*****@*****.**']) event = q.expect('stream-iq', to='conf.localhost', query_ns='http://jabber.org/protocol/disco#info') result = make_result_iq(stream, event.stanza) feature = result.firstChildElement().addElement('feature') feature['var'] = 'http://jabber.org/protocol/muc' stream.send(result) event = q.expect('dbus-return', method='RequestHandles') handles = event.value[0] room_handle = handles[0] # join the muc call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) _, stream_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='[email protected]/test')) # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', '*****@*****.**', 'test')) q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(cs.HT_CONTACT, [2, 3]) == \ ['[email protected]/test', '[email protected]/bob'] bob_handle = 3 event = q.expect('dbus-return', method='RequestChannel') text_chan = bus.get_object(conn.bus_name, event.value[0]) # Bob offers a muc tube tube_id = 666 stream_id = 1234 presence = make_muc_presence('owner', 'moderator', '*****@*****.**', 'bob') tubes = presence.addElement((ns.TUBES, 'tubes')) tube = tubes.addElement((None, 'tube')) tube['type'] = 'dbus' tube['service'] = 'org.telepathy.freedesktop.test' tube['id'] = str(tube_id) tube['stream-id'] = str(stream_id) tube['dbus-name'] = ':2.Y2Fzc2lkeS10ZXN0MgAA' tube['initiator'] = '[email protected]/bob' parameters = tube.addElement((None, 'parameters')) parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 's' parameter['type'] = 'str' parameter.addContent('hello') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'ay' parameter['type'] = 'bytes' parameter.addContent('aGVsbG8=') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'u' parameter['type'] = 'uint' parameter.addContent('123') parameter = parameters.addElement((None, 'parameter')) parameter['name'] = 'i' parameter['type'] = 'int' parameter.addContent('-123') stream.send(presence) # tubes channel is automatically created event = q.expect('dbus-signal', signal='NewChannel') if event.args[1] == cs.CHANNEL_TYPE_TEXT: # skip this one, try the next one event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TUBES, event.args assert event.args[2] == cs.HT_ROOM assert event.args[3] == room_handle tubes_chan = bus.get_object(conn.bus_name, event.args[0]) tubes_iface = dbus.Interface(tubes_chan, event.args[1]) channel_props = tubes_chan.GetAll( cs.CHANNEL, dbus_interface=dbus.PROPERTIES_IFACE) assert channel_props['TargetID'] == '*****@*****.**', channel_props assert channel_props['Requested'] == False assert channel_props['InitiatorID'] == '' assert channel_props['InitiatorHandle'] == 0 tubes_self_handle = tubes_chan.GetSelfHandle( dbus_interface=cs.CHANNEL_IFACE_GROUP) q.expect('dbus-signal', signal='NewTube', args=[tube_id, bob_handle, 0, 'org.telepathy.freedesktop.test', sample_parameters, 0]) expected_tube = (tube_id, bob_handle, cs.TUBE_TYPE_DBUS, 'org.telepathy.freedesktop.test', sample_parameters, cs.TUBE_STATE_LOCAL_PENDING) tubes = tubes_iface.ListTubes(byte_arrays=True) assert len(tubes) == 1, unwrap(tubes) t.check_tube_in_tubes(expected_tube, tubes) # reject the tube tubes_iface.CloseTube(tube_id) q.expect('dbus-signal', signal='TubeClosed', args=[tube_id]) # close the text channel text_chan.Close()
def test(q, bus, conn, sip): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) self_handle = conn.Get(cs.CONN, 'SelfHandle', dbus_interface=cs.PROPERTIES_IFACE) self_uri = conn.inspect_contact_sync(self_handle) contact = 'sip:[email protected]' handle = conn.get_contact_handle_sync(contact) chan, _ = conn.Requests.CreateChannel( { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: handle }) requested_obj, target_handle = test_new_channel (q, bus, conn, target_uri=contact, initiator_uri=self_uri, requested=True) assert requested_obj.object_path == chan, requested_obj.object_path assert target_handle == handle, (target_handle, handle) iface = dbus.Interface(requested_obj, cs.CHANNEL_TYPE_TEXT) iface.Send(0, 'Hello') event = q.expect('sip-message', uri='sip:[email protected]', body='Hello') sip.deliverResponse(sip.responseFromRequest(404, event.sip_message)) q.expect('dbus-signal', signal='SendError') iface.Send(0, 'Hello Again') event = q.expect('sip-message', uri='sip:[email protected]', body='Hello Again') sip.deliverResponse(sip.responseFromRequest(200, event.sip_message)) ua_via = twisted.protocols.sip.parseViaHeader(event.headers['via'][0]) conn.ReleaseHandles(1, [handle]) call_id = 'XYZ@localhost' send_message(sip, ua_via, 'Hi', call_id=call_id, time=1234567890) incoming_obj, handle = test_new_channel (q, bus, conn, target_uri=FROM_URL, initiator_uri=FROM_URL, requested=False) iface = dbus.Interface(incoming_obj, cs.CHANNEL_TYPE_TEXT) name = conn.inspect_contact_sync(handle) assert name == FROM_URL event = q.expect('dbus-signal', signal='MessageReceived') msg = event.args[0] now = time.time() assert msg[0]['message-token'] == "%s;cseq=%u" % (call_id, cseq_num) assert now - 10 < msg[0]['message-received'] < now + 10 assert msg[0]['message-sent'] == 1234567890 assert msg[1]['content-type'] == 'text/plain' assert msg[1]['content'] == 'Hi' # FIXME: times out for some reason, the response is in fact sent; # race condition with the earlier wait for 'dbus-signal'? #event = q.expect('sip-response', code=200) iface.AcknowledgePendingMessages([msg[0]['pending-message-id']]) # Test conversion from an 8-bit encoding. # Due to limited set of encodings available in some environments, # try with US ASCII and ISO 8859-1. send_message(sip, ua_via, u'straight ASCII'.encode('us-ascii'), encoding='us-ascii') event = q.expect('dbus-signal', signal='Received') assert event.args[5] == 'straight ASCII' iface.AcknowledgePendingMessages([event.args[0]]) send_message(sip, ua_via, u'Hyv\xe4!'.encode('iso-8859-1'), encoding='iso-8859-1') event = q.expect('dbus-signal', signal='Received') assert event.args[5] == u'Hyv\xe4!' conn.ReleaseHandles(1, [handle]) iface = dbus.Interface(incoming_obj, cs.CHANNEL_IFACE_DESTROYABLE) iface.Destroy() del iface event = q.expect('dbus-signal', signal='Closed') del incoming_obj # Sending the message to appear on the requested channel pending_msgs = [] send_message(sip, ua_via, 'How are you doing now, old pal?', sender=contact) event = q.expect('dbus-signal', signal='Received', path=chan) assert event.args[5] == 'How are you doing now, old pal?' pending_msgs.append(tuple(event.args)) send_message(sip, ua_via, 'I hope you can receive it', sender=contact) event = q.expect('dbus-signal', signal='Received') assert event.args[5] == 'I hope you can receive it' pending_msgs.append(tuple(event.args)) # Don't acknowledge the last messages, close the channel so that it's reopened dbus.Interface(requested_obj, cs.CHANNEL).Close() del requested_obj event = q.expect('dbus-signal', signal='Closed', path=chan) requested_obj, handle = test_new_channel (q, bus, conn, target_uri=contact, initiator_uri=contact, requested=False) # Expect Channel_Text_Message_Flag_Resqued to be set pending_msgs = [message_with_resqued(msg) for msg in pending_msgs] # The first message is the delivery report of the message we failed to # send so we'll skip it. iface = dbus.Interface(requested_obj, cs.CHANNEL_TYPE_TEXT) pending_res = iface.ListPendingMessages(False) assert pending_msgs == pending_res[1:], (pending_msgs, unwrap(pending_res)[1:]) pending_res = iface.ListPendingMessages(True) assert pending_msgs == pending_res[1:], (pending_msgs, unwrap(pending_res)[1:]) # There should be no pending messages any more pending_res = iface.ListPendingMessages(False) assert pending_res == [], pending_res del iface # Hit also the code path for closing the channel with no pending messages dbus.Interface(requested_obj, cs.CHANNEL).Close() event = q.expect('dbus-signal', signal='Closed') del requested_obj # Hit the message zapping path when the connection is disconnected send_message(sip, ua_via, 'Will you leave this unacknowledged?') test_new_channel (q, bus, conn, target_uri=FROM_URL, initiator_uri=FROM_URL, requested=False) conn.Disconnect() # Check the last channel with an unacknowledged message event = q.expect('dbus-signal', signal='Closed') q.expect('dbus-signal', signal='StatusChanged', args=[2,1])
def test(q, bus, conn): cm = bus.get_object(cs.CM + '.salut', tp_path_prefix + '/ConnectionManager/salut') cm_iface = dbus.Interface(cm, cs.CM) cm_prop_iface = dbus.Interface(cm, cs.PROPERTIES_IFACE) protocols = unwrap(cm_prop_iface.Get(cs.CM, 'Protocols')) assertEquals(set(['local-xmpp']), set(protocols.keys())) local_props = protocols['local-xmpp'] local_params = local_props[cs.PROTOCOL + '.Parameters'] proto = bus.get_object(cm.bus_name, cm.object_path + '/local_xmpp') proto_iface = dbus.Interface(proto, cs.PROTOCOL) proto_prop_iface = dbus.Interface(proto, cs.PROPERTIES_IFACE) proto_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL)) for key in [ 'Parameters', 'Interfaces', 'ConnectionInterfaces', 'RequestableChannelClasses', u'VCardField', u'EnglishName', u'Icon' ]: a = local_props[cs.PROTOCOL + '.' + key] b = proto_props[key] assertEquals(a, b) assertEquals('', proto_props['VCardField']) assertEquals('Link-local XMPP', proto_props['EnglishName']) assertEquals('im-local-xmpp', proto_props['Icon']) assertContains(cs.CONN_IFACE_ALIASING, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_AVATARS, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_CONTACTS, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_SIMPLE_PRESENCE, proto_props['ConnectionInterfaces']) assertContains(cs.CONN_IFACE_REQUESTS, proto_props['ConnectionInterfaces']) # local-xmpp has case-sensitive literals as identifiers assertEquals('SMcV@Reptile', unwrap(proto_iface.NormalizeContact('SMcV@Reptile'))) # (Only) 'first-name' and 'last-name' are mandatory for IdentifyAccount() call_async(q, proto_iface, 'IdentifyAccount', {'first-name': 'Simon'}) q.expect('dbus-error', method='IdentifyAccount', name=cs.INVALID_ARGUMENT) # Identifying an account doesn't do much, anyway test_params = {'first-name': 'Simon', 'last-name': 'McVittie'} acc_name = unwrap(proto_iface.IdentifyAccount(test_params)) assertEquals('', acc_name) assertContains(cs.PROTOCOL_IFACE_AVATARS, proto_props['Interfaces']) avatar_props = unwrap(proto_prop_iface.GetAll(cs.PROTOCOL_IFACE_AVATARS)) assertEquals(65535, avatar_props['MaximumAvatarBytes']) assertEquals(0, avatar_props['MaximumAvatarHeight']) assertEquals(0, avatar_props['MaximumAvatarWidth']) assertEquals(0, avatar_props['MinimumAvatarHeight']) assertEquals(0, avatar_props['MinimumAvatarWidth']) assertEquals(64, avatar_props['RecommendedAvatarHeight']) assertEquals(64, avatar_props['RecommendedAvatarWidth']) assertEquals(['image/png', 'image/jpeg'], avatar_props['SupportedAvatarMIMETypes']) assertContains(cs.PROTOCOL_IFACE_PRESENCES, proto_props['Interfaces']) expected_status = { 'available': (cs.PRESENCE_AVAILABLE, True, True), 'dnd': (cs.PRESENCE_BUSY, True, True), 'away': (cs.PRESENCE_AWAY, True, True), 'offline': (cs.PRESENCE_OFFLINE, False, False) } presences = proto_prop_iface.Get(cs.PROTOCOL_IFACE_PRESENCES, 'Statuses') assertEquals(expected_status, presences)
def test(q, bus, conn, stream): conn.Connect() properties = conn.GetAll( cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) assert properties.get('Channels') == [], properties['Channels'] assert ({cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, }, [cs.TARGET_HANDLE, cs.TARGET_ID, cs.STREAM_TUBE_SERVICE] ) in properties.get('RequestableChannelClasses'),\ unwrap(properties['RequestableChannelClasses']) _, vcard_event, roster_event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', query_ns=ns.ROSTER)) acknowledge_iq(stream, vcard_event.stanza) roster = roster_event.stanza roster['type'] = 'result' item = roster_event.query.addElement('item') item['jid'] = 'bob@localhost' item['subscription'] = 'both' stream.send(roster) presence = domish.Element(('jabber:client', 'presence')) presence['from'] = 'bob@localhost/Bob' presence['to'] = 'test@localhost/Resource' c = presence.addElement('c') c['xmlns'] = 'http://jabber.org/protocol/caps' c['node'] = 'http://example.com/ICantBelieveItsNotTelepathy' c['ver'] = '1.2.3' stream.send(presence) event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to='bob@localhost/Bob') result = event.stanza result['type'] = 'result' assert event.query['node'] == \ 'http://example.com/ICantBelieveItsNotTelepathy#1.2.3' feature = event.query.addElement('feature') feature['var'] = ns.TUBES stream.send(result) bob_handle = conn.get_contact_handle_sync('bob@localhost') def new_chan_predicate(e): types = [] for _, props in e.args[0]: types.append(props[cs.CHANNEL_TYPE]) return cs.CHANNEL_TYPE_STREAM_TUBE in types call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: 'the.service', }) ret, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) chan_path, props = ret.value # Ensure a tube to the same person; check it's the same one. # call_async(q, conn.Requests, 'EnsureChannel', # { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, # cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, # cs.TARGET_HANDLE: bob_handle, # cs.STREAM_TUBE_SERVICE: 'the.service', # }) # ret = q.expect('dbus-return', method='EnsureChannel') # yours, ensured_path, _ = ret.value # assert ensured_path == chan_path, (ensured_path, chan_path) # assert not yours chan = bus.get_object(conn.bus_name, chan_path) chan.Close() # Now let's try ensuring a new tube. call_async(q, conn.Requests, 'EnsureChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT, cs.TARGET_HANDLE: bob_handle, cs.STREAM_TUBE_SERVICE: 'the.service', }) ret, new_sig = q.expect_many( EventPattern('dbus-return', method='EnsureChannel'), EventPattern('dbus-signal', signal='NewChannels', predicate=new_chan_predicate), ) yours, path, props = ret.value assert yours emitted_props = new_sig.args[0][0][1] assert props == emitted_props, (props, emitted_props) chan = bus.get_object(conn.bus_name, path) chan.Close()