diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/test_disco.py | 155 | ||||
-rw-r--r-- | tests/test_events.py | 35 | ||||
-rw-r--r-- | tests/test_pubsubstanzas.py | 15 | ||||
-rw-r--r-- | tests/test_statemachine.py | 116 |
4 files changed, 321 insertions, 0 deletions
diff --git a/tests/test_disco.py b/tests/test_disco.py new file mode 100644 index 00000000..bbe285a6 --- /dev/null +++ b/tests/test_disco.py @@ -0,0 +1,155 @@ +import unittest +from xml.etree import cElementTree as ET +from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath +from . import xmlcompare + +import sleekxmpp.plugins.xep_0030 as sd + +def stanzaPlugin(stanza, plugin): + stanza.plugin_attrib_map[plugin.plugin_attrib] = plugin + stanza.plugin_tag_map["{%s}%s" % (plugin.namespace, plugin.name)] = plugin + +class testdisco(unittest.TestCase): + + def setUp(self): + self.sd = sd + stanzaPlugin(self.sd.Iq, self.sd.DiscoInfo) + stanzaPlugin(self.sd.Iq, self.sd.DiscoItems) + + def try3Methods(self, xmlstring, iq): + iq2 = self.sd.Iq(None, self.sd.ET.fromstring(xmlstring)) + values = iq2.getValues() + iq3 = self.sd.Iq() + iq3.setValues(values) + self.failUnless(xmlstring == str(iq) == str(iq2) == str(iq3), str(iq)+"3 methods for creating stanza don't match") + + def testCreateInfoQueryNoNode(self): + """Testing disco#info query with no node.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_info']['node'] = '' + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#info" /></iq>""" + self.try3Methods(xmlstring, iq) + + def testCreateInfoQueryWithNode(self): + """Testing disco#info query with a node.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_info']['node'] = 'foo' + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#info" node="foo" /></iq>""" + self.try3Methods(xmlstring, iq) + + def testCreateInfoQueryNoNode(self): + """Testing disco#items query with no node.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_items']['node'] = '' + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#items" /></iq>""" + self.try3Methods(xmlstring, iq) + + def testCreateItemsQueryWithNode(self): + """Testing disco#items query with a node.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_items']['node'] = 'foo' + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#items" node="foo" /></iq>""" + self.try3Methods(xmlstring, iq) + + def testInfoIdentities(self): + """Testing adding identities to disco#info.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_info']['node'] = 'foo' + iq['disco_info'].addIdentity('conference', 'text', 'Chatroom') + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#info" node="foo"><identity category="conference" type="text" name="Chatroom" /></query></iq>""" + self.try3Methods(xmlstring, iq) + + def testInfoFeatures(self): + """Testing adding features to disco#info.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_info']['node'] = 'foo' + iq['disco_info'].addFeature('foo') + iq['disco_info'].addFeature('bar') + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#info" node="foo"><feature var="foo" /><feature var="bar" /></query></iq>""" + self.try3Methods(xmlstring, iq) + + def testItems(self): + """Testing adding features to disco#info.""" + iq = self.sd.Iq() + iq['id'] = "0" + iq['disco_items']['node'] = 'foo' + iq['disco_items'].addItem('user@localhost') + iq['disco_items'].addItem('user@localhost', 'foo') + iq['disco_items'].addItem('user@localhost', 'bar', 'Testing') + xmlstring = """<iq id="0"><query xmlns="http://jabber.org/protocol/disco#items" node="foo"><item jid="user@localhost" /><item node="foo" jid="user@localhost" /><item node="bar" jid="user@localhost" name="Testing" /></query></iq>""" + self.try3Methods(xmlstring, iq) + + def testAddRemoveIdentities(self): + """Test adding and removing identities to disco#info stanza""" + ids = [('automation', 'commands', 'AdHoc'), + ('conference', 'text', 'ChatRoom')] + + info = self.sd.DiscoInfo() + info.addIdentity(*ids[0]) + self.failUnless(info.getIdentities() == [ids[0]]) + + info.delIdentity('automation', 'commands') + self.failUnless(info.getIdentities() == []) + + info.setIdentities(ids) + self.failUnless(info.getIdentities() == ids) + + info.delIdentity('automation', 'commands') + self.failUnless(info.getIdentities() == [ids[1]]) + + info.delIdentities() + self.failUnless(info.getIdentities() == []) + + def testAddRemoveFeatures(self): + """Test adding and removing features to disco#info stanza""" + features = ['foo', 'bar', 'baz'] + + info = self.sd.DiscoInfo() + info.addFeature(features[0]) + self.failUnless(info.getFeatures() == [features[0]]) + + info.delFeature('foo') + self.failUnless(info.getFeatures() == []) + + info.setFeatures(features) + self.failUnless(info.getFeatures() == features) + + info.delFeature('bar') + self.failUnless(info.getFeatures() == ['foo', 'baz']) + + info.delFeatures() + self.failUnless(info.getFeatures() == []) + + def testAddRemoveItems(self): + """Test adding and removing items to disco#items stanza""" + items = [('user@localhost', None, None), + ('user@localhost', 'foo', None), + ('user@localhost', 'bar', 'Test')] + + info = self.sd.DiscoItems() + self.failUnless(True, ""+str(items[0])) + + info.addItem(*(items[0])) + self.failUnless(info.getItems() == [items[0]], info.getItems()) + + info.delItem('user@localhost') + self.failUnless(info.getItems() == []) + + info.setItems(items) + self.failUnless(info.getItems() == items) + + info.delItem('user@localhost', 'foo') + self.failUnless(info.getItems() == [items[0], items[2]]) + + info.delItems() + self.failUnless(info.getItems() == []) + + + +suite = unittest.TestLoader().loadTestsFromTestCase(testdisco) diff --git a/tests/test_events.py b/tests/test_events.py new file mode 100644 index 00000000..11821dbb --- /dev/null +++ b/tests/test_events.py @@ -0,0 +1,35 @@ +import unittest + +class testevents(unittest.TestCase): + + def setUp(self): + import sleekxmpp.stanza.presence as p + self.p = p + + def testEventHappening(self): + "Test handler working" + import sleekxmpp + c = sleekxmpp.ClientXMPP('crap@wherever', 'password') + happened = [] + def handletestevent(event): + happened.append(True) + c.add_event_handler("test_event", handletestevent) + c.event("test_event", {}) + c.event("test_event", {}) + self.failUnless(happened == [True, True], "event did not get triggered twice") + + def testDelEvent(self): + "Test handler working, then deleted and not triggered" + import sleekxmpp + c = sleekxmpp.ClientXMPP('crap@wherever', 'password') + happened = [] + def handletestevent(event): + happened.append(True) + c.add_event_handler("test_event", handletestevent) + c.event("test_event", {}) + c.del_event_handler("test_event", handletestevent) + c.event("test_event", {}) # should not trigger because it was deleted + self.failUnless(happened == [True], "event did not get triggered the correct number of times") + + +suite = unittest.TestLoader().loadTestsFromTestCase(testevents) diff --git a/tests/test_pubsubstanzas.py b/tests/test_pubsubstanzas.py index 5353f907..dc41fc30 100644 --- a/tests/test_pubsubstanzas.py +++ b/tests/test_pubsubstanzas.py @@ -97,6 +97,21 @@ class testpubsubstanzas(unittest.TestCase): iq3.setValues(values) self.failUnless(xmlstring == str(iq) == str(iq2) == str(iq3)) + def testState(self): + "Testing iq/psstate stanzas" + from sleekxmpp.plugins import xep_0004 + iq = self.ps.Iq() + iq['psstate']['node']= 'mynode' + iq['psstate']['item']= 'myitem' + pl = ET.Element('{http://andyet.net/protocol/pubsubqueue}claimed') + iq['psstate']['payload'] = pl + xmlstring = """<iq id="0"><state xmlns="http://jabber.org/protocol/psstate" node="mynode" item="myitem"><claimed xmlns="http://andyet.net/protocol/pubsubqueue" /></state></iq>""" + iq2 = self.ps.Iq(None, self.ps.ET.fromstring(xmlstring)) + iq3 = self.ps.Iq() + values = iq2.getValues() + iq3.setValues(values) + self.failUnless(xmlstring == str(iq) == str(iq2) == str(iq3)) + def testDefault(self): "Testing iq/pubsub_owner/default stanzas" from sleekxmpp.plugins import xep_0004 diff --git a/tests/test_statemachine.py b/tests/test_statemachine.py new file mode 100644 index 00000000..6749c8de --- /dev/null +++ b/tests/test_statemachine.py @@ -0,0 +1,116 @@ +import unittest +import time, threading + +if __name__ == '__main__': + import sys, os + sys.path.insert(0, os.getcwd()) + import sleekxmpp.xmlstream.statemachine as sm + + +class testStateMachine(unittest.TestCase): + + def setUp(self): pass + + + def testDefaults(self): + "Test ensure transitions occur correctly in a single thread" + s = sm.StateMachine(('one','two','three')) +# self.assertTrue(s.one) + self.assertTrue(s['one']) +# self.failIf(s.two) + self.failIf(s['two']) + try: + s.booga + self.fail('s.booga is an invalid state and should throw an exception!') + except: pass #expected exception + + + def testTransitions(self): + "Test ensure transitions occur correctly in a single thread" + s = sm.StateMachine(('one','two','three')) +# self.assertTrue(s.one) + + self.assertTrue( s.transition('one', 'two') ) +# self.assertTrue( s.two ) + self.assertTrue( s['two'] ) +# self.failIf( s.one ) + self.failIf( s['one'] ) + + self.assertTrue( s.transition('two', 'three') ) + self.assertTrue( s['three'] ) + self.failIf( s['two'] ) + + self.assertTrue( s.transition('three', 'one') ) + self.assertTrue( s['one'] ) + self.failIf( s['three'] ) + + # should return False immediately w/ no wait: + self.failIf( s.transition('three', 'one') ) + self.assertTrue( s['one'] ) + self.failIf( s['three'] ) + + # test fail condition w/ a short delay: + self.failIf( s.transition('two', 'three') ) + + # Ensure bad states are weeded out: + try: + s.transition('blah', 'three') + s.fail('Exception expected') + except: pass + + try: + s.transition('one', 'blahblah') + s.fail('Exception expected') + except: pass + + + def testTransitionsBlocking(self): + "Test that transitions block from more than one thread" + + s = sm.StateMachine(('one','two','three')) + self.assertTrue(s['one']) + + now = time.time() + self.failIf( s.transition('two', 'one', wait=5.0) ) + self.assertTrue( time.time() > now + 4 ) + self.assertTrue( time.time() < now + 7 ) + + def testThreadedTransitions(self): + "Test that transitions are atomic in > one thread" + + s = sm.StateMachine(('one','two','three')) + self.assertTrue(s['one']) + + thread_state = {'ready': False, 'transitioned': False} + def t1(): + # this will block until the main thread transitions to 'two' + if s['two']: + print 'thread has already transitioned!' + self.fail() + thread_state['ready'] = True + print 'Thread is ready' + self.assertTrue( s.transition('two','three', wait=20) ) + print 'transitioned to three!' + thread_state['transitioned'] = True + + thread = threading.Thread(target=t1) + thread.daemon = True + thread.start() + start = time.time() + while not thread_state['ready']: + print 'not ready' + if time.time() > start+10: self.fail('Timeout waiting for thread to init!') + time.sleep(0.1) + time.sleep(0.2) # the thread should be blocking on the 'transition' call at this point. + self.failIf( thread_state['transitioned'] ) # ensure it didn't 'go' yet. + print 'transitioning to two!' + self.assertTrue( s.transition('one','two') ) + time.sleep(0.2) # second thread should have transitioned now: + self.assertTrue( thread_state['transitioned'] ) + + + + +suite = unittest.TestLoader().loadTestsFromTestCase(testStateMachine) + +if __name__ == '__main__': unittest.main() |