summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_plugins.py162
-rw-r--r--tests/test_stanza_xep_0009.py26
-rw-r--r--tests/test_stanza_xep_0047.py90
-rw-r--r--tests/test_stanza_xep_0085.py6
-rw-r--r--tests/test_stanza_xep_0184.py38
-rw-r--r--tests/test_stream_filters.py88
-rw-r--r--tests/test_stream_presence.py12
-rw-r--r--tests/test_stream_roster.py132
-rw-r--r--tests/test_stream_xep_0030.py16
-rw-r--r--tests/test_stream_xep_0047.py180
10 files changed, 729 insertions, 21 deletions
diff --git a/tests/test_plugins.py b/tests/test_plugins.py
new file mode 100644
index 00000000..6220d7a5
--- /dev/null
+++ b/tests/test_plugins.py
@@ -0,0 +1,162 @@
+import unittest
+import logging
+
+from sleekxmpp.plugins.base import PluginManager, BasePlugin, register_plugin
+
+
+class A(BasePlugin):
+ name = 'a'
+
+
+class B(BasePlugin):
+ name = 'b'
+
+
+class C(BasePlugin):
+ name = 'c'
+ dependencies = set(['b', 'd'])
+
+
+class D(BasePlugin):
+ name = 'd'
+ dependencies = set(['c'])
+
+
+class E(BasePlugin):
+ name = 'e'
+ dependencies = set(['a', 'd'])
+
+class F(BasePlugin):
+ name = 'f'
+ dependencies = set(['a', 'b'])
+
+
+register_plugin(A)
+register_plugin(B)
+register_plugin(C)
+register_plugin(D)
+register_plugin(E)
+register_plugin(F)
+
+
+class TestPlugins(unittest.TestCase):
+
+
+ def test_enable(self):
+ """Enable a single plugin."""
+ p = PluginManager(None)
+
+ events = []
+
+ def init(self):
+ events.append('init')
+
+ A.plugin_init = init
+
+ p.enable('a')
+
+ self.assertEqual(len(p), 1, "Wrong number of enabled plugins.")
+ self.assertEqual(events, ['init'], "Plugin init method not called.")
+
+ def test_disable(self):
+ """Disable a single plugin."""
+ p = PluginManager(None)
+
+ events = []
+
+ def init(self):
+ events.append('init')
+
+ def end(self):
+ events.append('end')
+
+ A.plugin_init = init
+ A.plugin_end = end
+
+ p.enable('a')
+ p.disable('a')
+
+ self.assertEqual(len(p), 0, "Wrong number of enabled plugins.")
+ self.assertEqual(events, ['init', 'end'],
+ "Plugin lifecycle methods not called.")
+
+ def test_enable_dependencies(self):
+ """Enable a plugin with acyclic dependencies."""
+ p = PluginManager(None)
+
+ events = []
+
+ A.plugin_init = lambda s: events.append('init_a')
+ B.plugin_init = lambda s: events.append('init_b')
+
+ p.enable('f')
+
+ self.assertEqual(len(p), 3, "Wrong number of enabled plugins.")
+ self.assertTrue('init_a' in events, "Dependency A not enabled.")
+ self.assertTrue('init_b' in events, "Dependency B not enabled.")
+
+ def test_enable_cyclic_dependencies(self):
+ """Enable a plugin with cyclic dependencies."""
+
+ p = PluginManager(None)
+
+ events = []
+
+ B.plugin_init = lambda s: events.append('init_b')
+ C.plugin_init = lambda s: events.append('init_c')
+ D.plugin_init = lambda s: events.append('init_d')
+
+ p.enable('c')
+
+ self.assertEqual(len(p), 3, "Wrong number of enabled plugins.")
+ self.assertTrue('init_b' in events, "Dependency B not enabled.")
+ self.assertTrue('init_c' in events, "Dependency C not enabled.")
+ self.assertTrue('init_d' in events, "Dependency D not enabled.")
+
+ def test_disable_dependendents(self):
+ """Disable a plugin with dependents."""
+
+ p = PluginManager(None)
+
+ events = []
+
+ A.plugin_end = lambda s: events.append('end_a')
+ B.plugin_end = lambda s: events.append('end_b')
+ F.plugin_end = lambda s: events.append('end_f')
+
+ p.enable('f')
+ p.disable('a')
+
+ self.assertEqual(len(p), 1, "Wrong number of enabled plugins.")
+ self.assertTrue('end_f' in events, "Dependent F not disabled.")
+ self.assertTrue('end_a' in events, "Plugin A not disabled.")
+
+ def test_disable_cyclic_dependents(self):
+ """Disable a plugin with cyclic dependents."""
+
+ p = PluginManager(None)
+
+ events = []
+
+ B.plugin_end = lambda s: events.append('end_b')
+ C.plugin_end = lambda s: events.append('end_c')
+ D.plugin_end = lambda s: events.append('end_d')
+
+ p.enable('c')
+ p.disable('b')
+
+ self.assertEqual(len(p), 0, "Wrong number of enabled plugins.")
+ self.assertTrue('end_b' in events, "Plugin B not disabled.")
+ self.assertTrue('end_c' in events, "Dependent C not disabled.")
+ self.assertTrue('end_d' in events, "Dependent D not disabled.")
+
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestPlugins)
+
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(levelname)-8s %(message)s')
+
+ tests = unittest.TestSuite([suite])
+ unittest.TextTestRunner(verbosity=2).run(tests)
diff --git a/tests/test_stanza_xep_0009.py b/tests/test_stanza_xep_0009.py
index 36800335..fa1ed19b 100644
--- a/tests/test_stanza_xep_0009.py
+++ b/tests/test_stanza_xep_0009.py
@@ -1,3 +1,5 @@
+# -*- encoding:utf-8 -*-
+
"""
SleekXMPP: The Sleek XMPP Library
Copyright (C) 2011 Nathanael C. Fritz, Dann Martens (TOMOTON).
@@ -6,7 +8,10 @@
See the file LICENSE for copying permission.
"""
+from __future__ import unicode_literals
+
import base64
+import sys
from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, \
MethodResponse
@@ -19,6 +24,9 @@ from sleekxmpp.xmlstream.tostring import tostring
import unittest
+if sys.version_info > (3, 0):
+ unicode = str
+
class TestJabberRPC(SleekTest):
@@ -114,6 +122,24 @@ class TestJabberRPC(SleekTest):
self.assertEqual(params, xml2py(expected_xml),
"XML to string conversion")
+ def testConvertUnicodeString(self):
+ params = ["おはよう"]
+ params_xml = py2xml(*params)
+ expected_xml = self.parse_xml("""
+ <params xmlns="jabber:iq:rpc">
+ <param>
+ <value>
+ <string>おはよう</string>
+ </value>
+ </param>
+ </params>
+ """)
+ self.assertTrue(self.compare(expected_xml, params_xml),
+ "String to XML conversion\nExpected: %s\nGot: %s" % (
+ tostring(expected_xml), tostring(params_xml)))
+ self.assertEqual(params, xml2py(expected_xml),
+ "XML to string conversion")
+
def testConvertInteger(self):
params = [32767, -32768]
params_xml = py2xml(*params)
diff --git a/tests/test_stanza_xep_0047.py b/tests/test_stanza_xep_0047.py
new file mode 100644
index 00000000..6aa2314b
--- /dev/null
+++ b/tests/test_stanza_xep_0047.py
@@ -0,0 +1,90 @@
+from sleekxmpp.test import *
+from sleekxmpp.plugins.xep_0047 import Data
+
+
+class TestIBB(SleekTest):
+
+ def setUp(self):
+ register_stanza_plugin(Iq, Data)
+
+ def testInvalidBase64MidEqual(self):
+ """
+ Test detecting invalid base64 data with = inside the
+ character data instead of at the end.
+ """
+ iq = Iq(xml=ET.fromstring("""
+ <iq type="set" id="0" to="tester@localhost">
+ <data xmlns="http://jabber.org/protocol/ibb" seq="0">
+ ABC=DEFGH
+ </data>
+ </iq>
+ """))
+
+ errored = False
+
+ try:
+ data = iq['ibb_data']['data']
+ except XMPPError:
+ errored = True
+
+ self.assertTrue(errored, "ABC=DEFGH did not raise base64 error")
+
+ def testInvalidBase64PrefixEqual(self):
+ """
+ Test detecting invalid base64 data with = as a prefix
+ to the character data.
+ """
+ iq = Iq(xml=ET.fromstring("""
+ <iq type="set" id="0" to="tester@localhost">
+ <data xmlns="http://jabber.org/protocol/ibb" seq="0">
+ =ABCDEFGH
+ </data>
+ </iq>
+ """))
+
+ errored = False
+
+ try:
+ data = iq['ibb_data']['data']
+ except XMPPError:
+ errored = True
+
+ self.assertTrue(errored, "=ABCDEFGH did not raise base64 error")
+
+ def testInvalidBase64Alphabet(self):
+ """
+ Test detecting invalid base64 data with characters
+ outside of the base64 alphabet.
+ """
+ iq = Iq(xml=ET.fromstring("""
+ <iq type="set" id="0" to="tester@localhost">
+ <data xmlns="http://jabber.org/protocol/ibb" seq="0">
+ ABCD?EFGH
+ </data>
+ </iq>
+ """))
+
+ errored = False
+
+ try:
+ data = iq['ibb_data']['data']
+ except XMPPError:
+ errored = True
+
+ self.assertTrue(errored, "ABCD?EFGH did not raise base64 error")
+
+ def testConvertData(self):
+ """Test that data is converted to base64"""
+ iq = Iq()
+ iq['type'] = 'set'
+ iq['ibb_data']['seq'] = 0
+ iq['ibb_data']['data'] = 'sleekxmpp'
+
+ self.check(iq, """
+ <iq type="set">
+ <data xmlns="http://jabber.org/protocol/ibb" seq="0">c2xlZWt4bXBw</data>
+ </iq>
+ """)
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestIBB)
diff --git a/tests/test_stanza_xep_0085.py b/tests/test_stanza_xep_0085.py
index b08404e2..61784e47 100644
--- a/tests/test_stanza_xep_0085.py
+++ b/tests/test_stanza_xep_0085.py
@@ -4,7 +4,11 @@ import sleekxmpp.plugins.xep_0085 as xep_0085
class TestChatStates(SleekTest):
def setUp(self):
- register_stanza_plugin(Message, xep_0085.ChatState)
+ register_stanza_plugin(Message, xep_0085.stanza.Active)
+ register_stanza_plugin(Message, xep_0085.stanza.Composing)
+ register_stanza_plugin(Message, xep_0085.stanza.Gone)
+ register_stanza_plugin(Message, xep_0085.stanza.Inactive)
+ register_stanza_plugin(Message, xep_0085.stanza.Paused)
def testCreateChatState(self):
"""Testing creating chat states."""
diff --git a/tests/test_stanza_xep_0184.py b/tests/test_stanza_xep_0184.py
new file mode 100644
index 00000000..13472373
--- /dev/null
+++ b/tests/test_stanza_xep_0184.py
@@ -0,0 +1,38 @@
+from sleekxmpp.test import *
+import sleekxmpp.plugins.xep_0184 as xep_0184
+
+
+class TestReciept(SleekTest):
+
+ def setUp(self):
+ register_stanza_plugin(Message, xep_0184.Request)
+ register_stanza_plugin(Message, xep_0184.Received)
+
+ def testCreateRequest(self):
+ request = """
+ <message>
+ <request xmlns="urn:xmpp:receipts" />
+ </message>
+ """
+
+ msg = self.Message()
+
+ self.assertEqual(msg['request_receipt'], False)
+
+ msg['request_receipt'] = True
+ self.check(msg, request)
+
+ def testCreateReceived(self):
+ received = """
+ <message>
+ <received xmlns="urn:xmpp:receipts" id="1" />
+ </message>
+ """
+
+ msg = self.Message()
+
+ msg['receipt'] = '1'
+ self.check(msg, received)
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestReciept)
diff --git a/tests/test_stream_filters.py b/tests/test_stream_filters.py
new file mode 100644
index 00000000..ef4d5dc8
--- /dev/null
+++ b/tests/test_stream_filters.py
@@ -0,0 +1,88 @@
+import time
+
+from sleekxmpp import Message
+from sleekxmpp.test import *
+from sleekxmpp.xmlstream.handler import *
+from sleekxmpp.xmlstream.matcher import *
+
+
+class TestFilters(SleekTest):
+
+ """
+ Test using incoming and outgoing filters.
+ """
+
+ def setUp(self):
+ self.stream_start()
+
+ def tearDown(self):
+ self.stream_close()
+
+ def testIncoming(self):
+
+ data = []
+
+ def in_filter(stanza):
+ if isinstance(stanza, Message):
+ if stanza['body'] == 'testing':
+ stanza['subject'] = stanza['body'] + ' filter'
+ print('>>> %s' % stanza['subject'])
+ return stanza
+
+ def on_message(msg):
+ print('<<< %s' % msg['subject'])
+ data.append(msg['subject'])
+
+ self.xmpp.add_filter('in', in_filter)
+ self.xmpp.add_event_handler('message', on_message)
+
+ self.recv("""
+ <message>
+ <body>no filter</body>
+ </message>
+ """)
+
+ self.recv("""
+ <message>
+ <body>testing</body>
+ </message>
+ """)
+
+ time.sleep(0.5)
+
+ self.assertEqual(data, ['', 'testing filter'],
+ 'Incoming filter did not apply %s' % data)
+
+ def testOutgoing(self):
+
+ def out_filter(stanza):
+ if isinstance(stanza, Message):
+ if stanza['body'] == 'testing':
+ stanza['body'] = 'changed!'
+ return stanza
+
+ self.xmpp.add_filter('out', out_filter)
+
+ m1 = self.Message()
+ m1['body'] = 'testing'
+ m1.send()
+
+ m2 = self.Message()
+ m2['body'] = 'blah'
+ m2.send()
+
+ self.send("""
+ <message>
+ <body>changed!</body>
+ </message>
+ """)
+
+ self.send("""
+ <message>
+ <body>blah</body>
+ </message>
+ """)
+
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestFilters)
diff --git a/tests/test_stream_presence.py b/tests/test_stream_presence.py
index 63ccb043..4f2ede16 100644
--- a/tests/test_stream_presence.py
+++ b/tests/test_stream_presence.py
@@ -7,6 +7,9 @@ class TestStreamPresence(SleekTest):
Test handling roster updates.
"""
+ def setUp(self):
+ self.stream_start(jid='tester@localhost', plugins=[])
+
def tearDown(self):
self.stream_close()
@@ -25,7 +28,6 @@ class TestStreamPresence(SleekTest):
# The presence_unavailable event should be triggered.
events.add('unavailable')
- self.stream_start()
self.xmpp.add_event_handler('got_offline', got_offline)
self.xmpp.add_event_handler('presence_unavailable', unavailable)
@@ -48,7 +50,6 @@ class TestStreamPresence(SleekTest):
def got_offline(presence):
events.append('got_offline')
- self.stream_start()
self.xmpp.add_event_handler('got_offline', got_offline)
# Setup roster. Use a 'set' instead of 'result' so we
@@ -98,7 +99,6 @@ class TestStreamPresence(SleekTest):
def got_online(p):
events.add('got_online')
- self.stream_start()
self.xmpp.add_event_handler('presence_available', presence_available)
self.xmpp.add_event_handler('got_online', got_online)
@@ -128,7 +128,6 @@ class TestStreamPresence(SleekTest):
def changed_subscription(p):
events.add('changed_subscription')
- self.stream_start(jid='tester@localhost')
self.xmpp.add_event_handler('changed_subscription',
changed_subscription)
@@ -175,8 +174,6 @@ class TestStreamPresence(SleekTest):
def changed_subscription(p):
events.add('changed_subscription')
- self.stream_start(jid='tester@localhost')
-
self.xmpp.add_event_handler('changed_subscription',
changed_subscription)
self.xmpp.add_event_handler('presence_subscribe',
@@ -205,8 +202,6 @@ class TestStreamPresence(SleekTest):
events = []
- self.stream_start()
-
ptypes = ['available', 'away', 'dnd', 'xa', 'chat',
'unavailable', 'subscribe', 'subscribed',
'unsubscribe', 'unsubscribed']
@@ -254,7 +249,6 @@ class TestStreamPresence(SleekTest):
def test_changed_status(self):
"""Test that the changed_status event is handled properly."""
events = []
- self.stream_start()
def changed_status(presence):
events.append(presence['type'])
diff --git a/tests/test_stream_roster.py b/tests/test_stream_roster.py
index 1f83f0ec..2d0da173 100644
--- a/tests/test_stream_roster.py
+++ b/tests/test_stream_roster.py
@@ -104,6 +104,74 @@ class TestStreamRoster(SleekTest):
self.failUnless('roster_update' in events,
"Roster updated event not triggered: %s" % events)
+ def testRosterPushRemove(self):
+ """Test handling roster item removal updates."""
+ self.stream_start(mode='client')
+ events = []
+
+ # Add roster item
+ self.recv("""
+ <iq to='tester@localhost' type="set" id="1">
+ <query xmlns="jabber:iq:roster">
+ <item jid="user@localhost"
+ name="User"
+ subscription="both">
+ <group>Friends</group>
+ <group>Examples</group>
+ </item>
+ </query>
+ </iq>
+ """)
+ self.send("""
+ <iq type="result" id="1">
+ <query xmlns="jabber:iq:roster" />
+ </iq>
+ """)
+
+ self.assertTrue('user@localhost' in self.xmpp.client_roster)
+
+ # Receive item remove push
+ self.recv("""
+ <iq to='tester@localhost' type="set" id="1">
+ <query xmlns="jabber:iq:roster">
+ <item jid="user@localhost"
+ subscription="remove">
+ </item>
+ </query>
+ </iq>
+ """)
+ self.send("""
+ <iq type="result" id="1">
+ <query xmlns="jabber:iq:roster" />
+ </iq>
+ """)
+
+ self.assertTrue('user@localhost' not in self.xmpp.client_roster)
+
+ def testUnauthorizedRosterPush(self):
+ """Test rejecting a roster push from an unauthorized source."""
+ self.stream_start()
+ self.recv("""
+ <iq to='tester@localhost' from="malicious_user@localhost"
+ type="set" id="1">
+ <query xmlns="jabber:iq:roster">
+ <item jid="user@localhost"
+ name="User"
+ subscription="both">
+ <group>Friends</group>
+ <group>Examples</group>
+ </item>
+ </query>
+ </iq>
+ """)
+ self.send("""
+ <iq to="malicious_user@localhost" type="error" id="1">
+ <error type="cancel" code="503">
+ <service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
+ </error>
+ </iq>
+ """)
+
def testRosterTimeout(self):
"""Test handling a timed out roster request."""
self.stream_start()
@@ -125,7 +193,8 @@ class TestStreamRoster(SleekTest):
# Since get_roster blocks, we need to run it in a thread.
t = threading.Thread(name='get_roster',
target=self.xmpp.get_roster,
- kwargs={str('callback'): roster_callback})
+ kwargs={str('block'): False,
+ str('callback'): roster_callback})
t.start()
self.send("""
@@ -157,7 +226,7 @@ class TestStreamRoster(SleekTest):
def testRosterUnicode(self):
"""Test that JIDs with Unicode values are handled properly."""
- self.stream_start()
+ self.stream_start(plugins=[])
self.recv("""
<iq to="tester@localhost" type="set" id="1">
<query xmlns="jabber:iq:roster">
@@ -198,7 +267,7 @@ class TestStreamRoster(SleekTest):
def testSendLastPresence(self):
"""Test that sending the last presence works."""
- self.stream_start()
+ self.stream_start(plugins=[])
self.xmpp.send_presence(pshow='dnd')
self.xmpp.auto_authorize = True
self.xmpp.auto_subscribe = True
@@ -226,5 +295,62 @@ class TestStreamRoster(SleekTest):
</presence>
""")
+ def testUnsupportedRosterVer(self):
+ """Test working with a server without roster versioning."""
+ self.stream_start()
+ self.assertTrue('rosterver' not in self.xmpp.features)
+
+ t = threading.Thread(name='get_roster', target=self.xmpp.get_roster)
+ t.start()
+ self.send("""
+ <iq type="get" id="1">
+ <query xmlns="jabber:iq:roster" />
+ </iq>
+ """)
+ self.recv("""
+ <iq to="tester@localhost" type="result" id="1" />
+ """)
+
+ t.join()
+
+ def testBootstrapRosterVer(self):
+ """Test bootstrapping with roster versioning."""
+ self.stream_start()
+ self.xmpp.features.add('rosterver')
+ self.xmpp.client_roster.version = ''
+
+ t = threading.Thread(name='get_roster', target=self.xmpp.get_roster)
+ t.start()
+ self.send("""
+ <iq type="get" id="1">
+ <query xmlns="jabber:iq:roster" ver="" />
+ </iq>
+ """)
+ self.recv("""
+ <iq to="tester@localhost" type="result" id="1" />
+ """)
+
+ t.join()
+
+
+ def testExistingRosterVer(self):
+ """Test using a stored roster version."""
+ self.stream_start()
+ self.xmpp.features.add('rosterver')
+ self.xmpp.client_roster.version = '42'
+
+ t = threading.Thread(name='get_roster', target=self.xmpp.get_roster)
+ t.start()
+ self.send("""
+ <iq type="get" id="1">
+ <query xmlns="jabber:iq:roster" ver="42" />
+ </iq>
+ """)
+ self.recv("""
+ <iq to="tester@localhost" type="result" id="1" />
+ """)
+
+ t.join()
+
suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamRoster)
diff --git a/tests/test_stream_xep_0030.py b/tests/test_stream_xep_0030.py
index 1666d3a1..dd43778a 100644
--- a/tests/test_stream_xep_0030.py
+++ b/tests/test_stream_xep_0030.py
@@ -122,7 +122,7 @@ class TestStreamDisco(SleekTest):
self.stream_start(mode='client',
plugins=['xep_0030'])
- def dynamic_jid(jid, node, iq):
+ 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')
@@ -158,7 +158,7 @@ class TestStreamDisco(SleekTest):
jid='tester.localhost',
plugins=['xep_0030'])
- def dynamic_global(jid, node, iq):
+ 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')
@@ -194,7 +194,7 @@ class TestStreamDisco(SleekTest):
self.stream_start(mode='client',
plugins=['xep_0030'])
- def dynamic_jid(jid, node, iq):
+ 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')
@@ -236,7 +236,7 @@ class TestStreamDisco(SleekTest):
jid='tester.localhost',
plugins=['xep_0030'])
- def dynamic_global(jid, node, iq):
+ 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')
@@ -325,7 +325,7 @@ class TestStreamDisco(SleekTest):
self.stream_start(mode='client',
plugins=['xep_0030'])
- def dynamic_jid(jid, node, iq):
+ 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')
@@ -359,7 +359,7 @@ class TestStreamDisco(SleekTest):
jid='tester.localhost',
plugins=['xep_0030'])
- def dynamic_global(jid, node, iq):
+ 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')
@@ -393,7 +393,7 @@ class TestStreamDisco(SleekTest):
self.stream_start(mode='client',
plugins=['xep_0030'])
- def dynamic_jid(jid, node, iq):
+ 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')
@@ -435,7 +435,7 @@ class TestStreamDisco(SleekTest):
jid='tester.localhost',
plugins=['xep_0030'])
- def dynamic_global(jid, node, iq):
+ 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')
diff --git a/tests/test_stream_xep_0047.py b/tests/test_stream_xep_0047.py
new file mode 100644
index 00000000..d8cdd6a3
--- /dev/null
+++ b/tests/test_stream_xep_0047.py
@@ -0,0 +1,180 @@
+import threading
+import time
+
+from sleekxmpp.test import *
+
+
+class TestInBandByteStreams(SleekTest):
+
+ def setUp(self):
+ self.stream_start(plugins=['xep_0047', 'xep_0030'])
+
+ def tearDown(self):
+ self.stream_close()
+
+ def testOpenStream(self):
+ """Test requesting a stream, successfully"""
+
+ events = []
+
+ def on_stream_start(stream):
+ events.append('ibb_stream_start')
+
+
+ self.xmpp.add_event_handler('ibb_stream_start', on_stream_start)
+
+ t = threading.Thread(name='open_stream',
+ target=self.xmpp['xep_0047'].open_stream,
+ args=('tester@localhost/receiver',),
+ kwargs={'sid': 'testing'})
+ t.start()
+
+ self.send("""
+ <iq type="set" to="tester@localhost/receiver" id="1">
+ <open xmlns="http://jabber.org/protocol/ibb"
+ sid="testing"
+ block-size="4096"
+ stanza="iq" />
+ </iq>
+ """)
+
+ self.recv("""
+ <iq type="result" id="1"
+ to="tester@localhost"
+ from="tester@localhost/receiver" />
+ """)
+
+ t.join()
+
+ time.sleep(0.2)
+
+ self.assertEqual(events, ['ibb_stream_start'])
+
+ def testAysncOpenStream(self):
+ """Test requesting a stream, aysnc"""
+
+ events = set()
+
+ def on_stream_start(stream):
+ events.add('ibb_stream_start')
+
+ def stream_callback(iq):
+ events.add('callback')
+
+ self.xmpp.add_event_handler('ibb_stream_start', on_stream_start)
+
+ t = threading.Thread(name='open_stream',
+ target=self.xmpp['xep_0047'].open_stream,
+ args=('tester@localhost/receiver',),
+ kwargs={'sid': 'testing',
+ 'block': False,
+ 'callback': stream_callback})
+ t.start()
+
+ self.send("""
+ <iq type="set" to="tester@localhost/receiver" id="1">
+ <open xmlns="http://jabber.org/protocol/ibb"
+ sid="testing"
+ block-size="4096"
+ stanza="iq" />
+ </iq>
+ """)
+
+ self.recv("""
+ <iq type="result" id="1"
+ to="tester@localhost"
+ from="tester@localhost/receiver" />
+ """)
+
+ t.join()
+
+ time.sleep(0.2)
+
+ self.assertEqual(events, set(['ibb_stream_start', 'callback']))
+
+ def testSendData(self):
+ """Test sending data over an in-band bytestream."""
+
+ streams = []
+ data = []
+
+ def on_stream_start(stream):
+ streams.append(stream)
+
+ def on_stream_data(d):
+ data.append(d['data'])
+
+ self.xmpp.add_event_handler('ibb_stream_start', on_stream_start)
+ self.xmpp.add_event_handler('ibb_stream_data', on_stream_data)
+
+ t = threading.Thread(name='open_stream',
+ target=self.xmpp['xep_0047'].open_stream,
+ args=('tester@localhost/receiver',),
+ kwargs={'sid': 'testing'})
+ t.start()
+
+ self.send("""
+ <iq type="set" to="tester@localhost/receiver" id="1">
+ <open xmlns="http://jabber.org/protocol/ibb"
+ sid="testing"
+ block-size="4096"
+ stanza="iq" />
+ </iq>
+ """)
+
+ self.recv("""
+ <iq type="result" id="1"
+ to="tester@localhost"
+ from="tester@localhost/receiver" />
+ """)
+
+ t.join()
+
+ time.sleep(0.2)
+
+ stream = streams[0]
+
+
+ # Test sending data out
+ stream.send("Testing")
+
+ self.send("""
+ <iq type="set" id="2"
+ from="tester@localhost"
+ to="tester@localhost/receiver">
+ <data xmlns="http://jabber.org/protocol/ibb"
+ seq="0"
+ sid="testing">
+ VGVzdGluZw==
+ </data>
+ </iq>
+ """)
+
+ self.recv("""
+ <iq type="result" id="2"
+ to="tester@localhost"
+ from="tester@localhost/receiver" />
+ """)
+
+ # Test receiving data
+ self.recv("""
+ <iq type="set" id="A"
+ to="tester@localhost"
+ from="tester@localhost/receiver">
+ <data xmlns="http://jabber.org/protocol/ibb"
+ seq="0"
+ sid="testing">
+ aXQgd29ya3Mh
+ </data>
+ </iq>
+ """)
+
+ self.send("""
+ <iq type="result" id="A"
+ to="tester@localhost/receiver" />
+ """)
+
+ self.assertEqual(data, ['it works!'])
+
+
+suite = unittest.TestLoader().loadTestsFromTestCase(TestInBandByteStreams)