597 lines
20 KiB
Python
597 lines
20 KiB
Python
import asyncio
|
|
import time
|
|
|
|
import unittest
|
|
from slixmpp.test import SlixTest
|
|
|
|
|
|
class TestStreamDisco(SlixTest):
|
|
|
|
"""
|
|
Test using the XEP-0030 plugin.
|
|
"""
|
|
|
|
def tearDown(self):
|
|
self.stream_close()
|
|
|
|
def testInfoEmptyDefaultNode(self):
|
|
"""
|
|
Info query result from an entity MUST have at least one identity
|
|
and feature, namely http://jabber.org/protocol/disco#info.
|
|
|
|
Since the XEP-0030 plugin is loaded, a disco response should
|
|
be generated and not an error result.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info">
|
|
<identity category="client" type="bot" />
|
|
<feature var="http://jabber.org/protocol/disco#info" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testInfoEmptyDefaultNodeComponent(self):
|
|
"""
|
|
Test requesting an empty, default node using a Component.
|
|
"""
|
|
self.stream_start(mode='component',
|
|
jid='tester.localhost',
|
|
plugins=['xep_0030'])
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info">
|
|
<identity category="component" type="generic" />
|
|
<feature var="http://jabber.org/protocol/disco#info" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testInfoIncludeNode(self):
|
|
"""
|
|
Results for info queries directed to a particular node MUST
|
|
include the node in the query response.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
|
|
self.xmpp['xep_0030'].static.add_node(node='testing')
|
|
|
|
self.recv("""
|
|
<iq to="tester@localhost/resource" type="get" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing">
|
|
</query>
|
|
</iq>""",
|
|
method='mask')
|
|
|
|
def testItemsIncludeNode(self):
|
|
"""
|
|
Results for items queries directed to a particular node MUST
|
|
include the node in the query response.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
|
|
self.xmpp['xep_0030'].static.add_node(node='testing')
|
|
|
|
self.recv("""
|
|
<iq to="tester@localhost/resource" type="get" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing">
|
|
</query>
|
|
</iq>""",
|
|
method='mask')
|
|
|
|
def testDynamicInfoJID(self):
|
|
"""
|
|
Test using a dynamic info handler for a particular JID.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_jid(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoInfo()
|
|
result['node'] = node
|
|
result.add_identity('client', 'console', name='Dynamic Info')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_info',
|
|
jid='tester@localhost',
|
|
handler=dynamic_jid)
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test" to="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing">
|
|
<identity category="client"
|
|
type="console"
|
|
name="Dynamic Info" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testDynamicInfoGlobal(self):
|
|
"""
|
|
Test using a dynamic info handler for all requests.
|
|
"""
|
|
self.stream_start(mode='component',
|
|
jid='tester.localhost',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_global(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoInfo()
|
|
result['node'] = node
|
|
result.add_identity('component', 'generic', name='Dynamic Info')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_info',
|
|
handler=dynamic_global)
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test"
|
|
to="user@tester.localhost"
|
|
from="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test"
|
|
to="tester@localhost"
|
|
from="user@tester.localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing">
|
|
<identity category="component"
|
|
type="generic"
|
|
name="Dynamic Info" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testOverrideJIDInfoHandler(self):
|
|
"""Test overriding a JID info handler."""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_jid(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoInfo()
|
|
result['node'] = node
|
|
result.add_identity('client', 'console', name='Dynamic Info')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_info',
|
|
jid='tester@localhost',
|
|
handler=dynamic_jid)
|
|
|
|
|
|
self.xmpp['xep_0030'].restore_defaults(jid='tester@localhost',
|
|
node='testing')
|
|
|
|
self.xmpp['xep_0030'].add_identity(jid='tester@localhost',
|
|
node='testing',
|
|
category='automation',
|
|
itype='command-list')
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test" to="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing">
|
|
<identity category="automation"
|
|
type="command-list" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testOverrideGlobalInfoHandler(self):
|
|
"""Test overriding the global JID info handler."""
|
|
self.stream_start(mode='component',
|
|
jid='tester.localhost',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_global(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoInfo()
|
|
result['node'] = node
|
|
result.add_identity('component', 'generic', name='Dynamic Info')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_info',
|
|
handler=dynamic_global)
|
|
|
|
self.xmpp['xep_0030'].restore_defaults(jid='user@tester.localhost',
|
|
node='testing')
|
|
|
|
self.xmpp['xep_0030'].add_feature(jid='user@tester.localhost',
|
|
node='testing',
|
|
feature='urn:xmpp:ping')
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test"
|
|
to="user@tester.localhost"
|
|
from="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test"
|
|
to="tester@localhost"
|
|
from="user@tester.localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="testing">
|
|
<feature var="urn:xmpp:ping" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testGetInfoRemote(self):
|
|
"""
|
|
Test sending a disco#info query to another entity
|
|
and receiving the result.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
events = set()
|
|
|
|
def handle_disco_info(iq):
|
|
events.add('disco_info')
|
|
|
|
|
|
self.xmpp.add_event_handler('disco_info', handle_disco_info)
|
|
|
|
|
|
self.xmpp.wrap(self.xmpp['xep_0030'].get_info('user@localhost', 'foo'))
|
|
self.wait_()
|
|
|
|
self.send("""
|
|
<iq type="get" to="user@localhost" id="1">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="foo" />
|
|
</iq>
|
|
""")
|
|
|
|
self.recv("""
|
|
<iq type="result" to="tester@localhost" id="1">
|
|
<query xmlns="http://jabber.org/protocol/disco#info"
|
|
node="foo">
|
|
<identity category="client" type="bot" />
|
|
<feature var="urn:xmpp:ping" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
self.assertEqual(events, {'disco_info'},
|
|
"Disco info event was not triggered: %s" % events)
|
|
|
|
def testDynamicItemsJID(self):
|
|
"""
|
|
Test using a dynamic items handler for a particular JID.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_jid(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoItems()
|
|
result['node'] = node
|
|
result.add_item('tester@localhost', node='foo', name='JID')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_items',
|
|
jid='tester@localhost',
|
|
handler=dynamic_jid)
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test" to="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing">
|
|
<item jid="tester@localhost" node="foo" name="JID" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testDynamicItemsGlobal(self):
|
|
"""
|
|
Test using a dynamic items handler for all requests.
|
|
"""
|
|
self.stream_start(mode='component',
|
|
jid='tester.localhost',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_global(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoItems()
|
|
result['node'] = node
|
|
result.add_item('tester@localhost', node='foo', name='Global')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_items',
|
|
handler=dynamic_global)
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test"
|
|
to="user@tester.localhost"
|
|
from="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test"
|
|
to="tester@localhost"
|
|
from="user@tester.localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing">
|
|
<item jid="tester@localhost" node="foo" name="Global" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testOverrideJIDItemsHandler(self):
|
|
"""Test overriding a JID items handler."""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_jid(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoItems()
|
|
result['node'] = node
|
|
result.add_item('tester@localhost', node='foo', name='Global')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_items',
|
|
jid='tester@localhost',
|
|
handler=dynamic_jid)
|
|
|
|
|
|
self.xmpp['xep_0030'].restore_defaults(jid='tester@localhost',
|
|
node='testing')
|
|
|
|
self.xmpp['xep_0030'].add_item(ijid='tester@localhost',
|
|
node='testing',
|
|
jid='tester@localhost',
|
|
subnode='foo',
|
|
name='Test')
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test" to="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing">
|
|
<item jid="tester@localhost" node="foo" name="Test" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testOverrideGlobalItemsHandler(self):
|
|
"""Test overriding the global JID items handler."""
|
|
self.stream_start(mode='component',
|
|
jid='tester.localhost',
|
|
plugins=['xep_0030'])
|
|
|
|
def dynamic_global(jid, node, ifrom, iq):
|
|
result = self.xmpp['xep_0030'].stanza.DiscoItems()
|
|
result['node'] = node
|
|
result.add_item('tester.localhost', node='foo', name='Global')
|
|
return result
|
|
|
|
self.xmpp['xep_0030'].set_node_handler('get_items',
|
|
handler=dynamic_global)
|
|
|
|
self.xmpp['xep_0030'].restore_defaults(jid='user@tester.localhost',
|
|
node='testing')
|
|
|
|
self.xmpp['xep_0030'].add_item(ijid='user@tester.localhost',
|
|
node='testing',
|
|
jid='user@tester.localhost',
|
|
subnode='foo',
|
|
name='Test')
|
|
|
|
self.recv("""
|
|
<iq type="get" id="test"
|
|
to="user@tester.localhost"
|
|
from="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing" />
|
|
</iq>
|
|
""")
|
|
|
|
self.send("""
|
|
<iq type="result" id="test"
|
|
to="tester@localhost"
|
|
from="user@tester.localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="testing">
|
|
<item jid="user@tester.localhost" node="foo" name="Test" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
def testGetItemsRemote(self):
|
|
"""
|
|
Test sending a disco#items query to another entity
|
|
and receiving the result.
|
|
"""
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030'])
|
|
|
|
events = set()
|
|
results = set()
|
|
|
|
def handle_disco_items(iq):
|
|
events.add('disco_items')
|
|
results.update(iq['disco_items']['items'])
|
|
|
|
|
|
self.xmpp.add_event_handler('disco_items', handle_disco_items)
|
|
|
|
self.xmpp.wrap(self.xmpp['xep_0030'].get_items('user@localhost', 'foo'))
|
|
self.wait_()
|
|
|
|
self.send("""
|
|
<iq type="get" to="user@localhost" id="1">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="foo" />
|
|
</iq>
|
|
""")
|
|
|
|
self.recv("""
|
|
<iq type="result" to="tester@localhost" id="1">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="foo">
|
|
<item jid="user@localhost" node="bar" name="Test" />
|
|
<item jid="user@localhost" node="baz" name="Test 2" />
|
|
</query>
|
|
</iq>
|
|
""")
|
|
|
|
items = {('user@localhost', 'bar', 'Test'),
|
|
('user@localhost', 'baz', 'Test 2')}
|
|
self.assertEqual(events, {'disco_items'},
|
|
"Disco items event was not triggered: %s" % events)
|
|
self.assertEqual(results, items,
|
|
"Unexpected items: %s" % results)
|
|
|
|
def testGetItemsIterators(self):
|
|
"""Test interaction between XEP-0030 and XEP-0059 plugins."""
|
|
iteration_finished = []
|
|
jids_found = set()
|
|
|
|
self.stream_start(mode='client',
|
|
plugins=['xep_0030', 'xep_0059'])
|
|
|
|
async def run_test():
|
|
iterator = await self.xmpp['xep_0030'].get_items(
|
|
jid='foo@localhost',
|
|
node='bar',
|
|
iterator=True
|
|
)
|
|
iterator.amount = 10
|
|
async for page in iterator:
|
|
for item in page['disco_items']['items']:
|
|
jids_found.add(item[0])
|
|
iteration_finished.append(True)
|
|
|
|
test_run = self.xmpp.wrap(run_test())
|
|
self.wait_()
|
|
self.send("""
|
|
<iq id="2" type="get" to="foo@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="bar">
|
|
<set xmlns="http://jabber.org/protocol/rsm">
|
|
<max>10</max>
|
|
</set>
|
|
</query>
|
|
</iq>
|
|
""")
|
|
self.recv("""
|
|
<iq id="2" type="result" to="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items">
|
|
<item jid="a@b" node="1"/>
|
|
<item jid="b@b" node="2"/>
|
|
<item jid="c@b" node="3"/>
|
|
<item jid="d@b" node="4"/>
|
|
<item jid="e@b" node="5"/>
|
|
<set xmlns="http://jabber.org/protocol/rsm">
|
|
<first index='0'>a@b</first>
|
|
<last>e@b</last>
|
|
<count>10</count>
|
|
</set>
|
|
</query>
|
|
</iq>
|
|
""")
|
|
self.wait_()
|
|
self.send("""
|
|
<iq id="3" type="get" to="foo@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items"
|
|
node="bar">
|
|
<set xmlns="http://jabber.org/protocol/rsm">
|
|
<max>10</max>
|
|
<after>e@b</after>
|
|
</set>
|
|
</query>
|
|
</iq>
|
|
""")
|
|
self.recv("""
|
|
<iq id="3" type="result" to="tester@localhost">
|
|
<query xmlns="http://jabber.org/protocol/disco#items">
|
|
<item jid="f@b" node="6"/>
|
|
<item jid="g@b" node="7"/>
|
|
<item jid="h@b" node="8"/>
|
|
<item jid="i@b" node="9"/>
|
|
<item jid="j@b" node="10"/>
|
|
<set xmlns="http://jabber.org/protocol/rsm">
|
|
<first index='5'>f@b</first>
|
|
<last>j@b</last>
|
|
<count>10</count>
|
|
</set>
|
|
</query>
|
|
</iq>
|
|
""")
|
|
expected_jids = {'%s@b' % i for i in 'abcdefghij'}
|
|
self.run_coro(test_run)
|
|
self.assertEqual(expected_jids, jids_found)
|
|
self.assertEqual(iteration_finished, [True])
|
|
|
|
|
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamDisco)
|