diff options
Diffstat (limited to 'tests')
40 files changed, 2621 insertions, 138 deletions
diff --git a/tests/test_events.py b/tests/test_events.py index fb34be30..a41ed017 100644 --- a/tests/test_events.py +++ b/tests/test_events.py @@ -1,5 +1,6 @@ import time -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestEvents(SleekTest): diff --git a/tests/test_jid.py b/tests/test_jid.py index ef1145d3..ed2aeea9 100644 --- a/tests/test_jid.py +++ b/tests/test_jid.py @@ -1,5 +1,9 @@ -from sleekxmpp.test import * -from sleekxmpp.xmlstream.jid import JID +# -*- encoding: utf8 -*- +from __future__ import unicode_literals +import unittest +from sleekxmpp.test import SleekTest +from sleekxmpp import JID, InvalidJID +from sleekxmpp.jid import nodeprep class TestJIDClass(SleekTest): @@ -137,5 +141,150 @@ class TestJIDClass(SleekTest): self.assertFalse(jid1 == jid2, "Same JIDs are not considered equal") self.assertTrue(jid1 != jid2, "Same JIDs are considered not equal") + def testZeroLengthDomain(self): + self.assertRaises(InvalidJID, JID, domain='') + self.assertRaises(InvalidJID, JID, 'user@/resource') + + def testZeroLengthLocalPart(self): + self.assertRaises(InvalidJID, JID, local='', domain='test.com') + self.assertRaises(InvalidJID, JID, '@/test.com') + + def testZeroLengthResource(self): + self.assertRaises(InvalidJID, JID, domain='test.com', resource='') + self.assertRaises(InvalidJID, JID, 'test.com/') + + def test1023LengthDomain(self): + domain = ('a.' * 509) + 'a.com' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + def test1023LengthLocalPart(self): + local = 'a' * 1023 + jid1 = JID(local=local, domain='test.com') + jid2 = JID('%s@test.com' % local) + + def test1023LengthResource(self): + resource = 'r' * 1023 + jid1 = JID(domain='test.com', resource=resource) + jid2 = JID('test.com/%s' % resource) + + def test1024LengthDomain(self): + domain = ('a.' * 509) + 'aa.com' + self.assertRaises(InvalidJID, JID, domain=domain) + self.assertRaises(InvalidJID, JID, 'user@%s/resource' % domain) + + def test1024LengthLocalPart(self): + local = 'a' * 1024 + self.assertRaises(InvalidJID, JID, local=local, domain='test.com') + self.assertRaises(InvalidJID, JID, '%s@/test.com' % local) + + def test1024LengthResource(self): + resource = 'r' * 1024 + self.assertRaises(InvalidJID, JID, domain='test.com', resource=resource) + self.assertRaises(InvalidJID, JID, 'test.com/%s' % resource) + + def testTooLongDomainLabel(self): + domain = ('a' * 64) + '.com' + self.assertRaises(InvalidJID, JID, domain=domain) + self.assertRaises(InvalidJID, JID, 'user@%s/resource' % domain) + + def testDomainEmptyLabel(self): + domain = 'aaa..bbb.com' + self.assertRaises(InvalidJID, JID, domain=domain) + self.assertRaises(InvalidJID, JID, 'user@%s/resource' % domain) + + def testDomainIPv4(self): + domain = '127.0.0.1' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + def testDomainIPv6(self): + domain = '[::1]' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + def testDomainInvalidIPv6NoBrackets(self): + domain = '::1' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + self.assertEqual(jid1.domain, '[::1]') + self.assertEqual(jid2.domain, '[::1]') + + def testDomainInvalidIPv6MissingBracket(self): + domain = '[::1' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + self.assertEqual(jid1.domain, '[::1]') + self.assertEqual(jid2.domain, '[::1]') + + def testDomainWithPort(self): + domain = 'example.com:5555' + self.assertRaises(InvalidJID, JID, domain=domain) + self.assertRaises(InvalidJID, JID, 'user@%s/resource' % domain) + + def testDomainWithTrailingDot(self): + domain = 'example.com.' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + self.assertEqual(jid1.domain, 'example.com') + self.assertEqual(jid2.domain, 'example.com') + + def testDomainWithDashes(self): + domain = 'example.com-' + self.assertRaises(InvalidJID, JID, domain=domain) + self.assertRaises(InvalidJID, JID, 'user@%s/resource' % domain) + + domain = '-example.com' + self.assertRaises(InvalidJID, JID, domain=domain) + self.assertRaises(InvalidJID, JID, 'user@%s/resource' % domain) + + def testACEDomain(self): + domain = 'xn--bcher-kva.ch' + jid1 = JID(domain=domain) + jid2 = JID('user@%s/resource' % domain) + + self.assertEqual(jid1.domain.encode('utf-8'), b'b\xc3\xbccher.ch') + self.assertEqual(jid2.domain.encode('utf-8'), b'b\xc3\xbccher.ch') + + def testJIDEscapeExistingSequences(self): + jid = JID(local='blah\\foo\\20bar', domain='example.com') + self.assertEqual(jid.local, 'blah\\foo\\5c20bar') + + def testJIDEscape(self): + jid = JID(local='here\'s_a_wild_&_/cr%zy/_address_for:<wv>("IMPS")', + domain='example.com') + self.assertEqual(jid.local, r'here\27s_a_wild_\26_\2fcr%zy\2f_address_for\3a\3cwv\3e(\22IMPS\22)') + + def testJIDUnescape(self): + jid = JID(local='here\'s_a_wild_&_/cr%zy/_address_for:<wv>("IMPS")', + domain='example.com') + ujid = jid.unescape() + self.assertEqual(ujid.local, 'here\'s_a_wild_&_/cr%zy/_address_for:<wv>("IMPS")') + + jid = JID(local='blah\\foo\\20bar', domain='example.com') + ujid = jid.unescape() + self.assertEqual(ujid.local, 'blah\\foo\\20bar') + + def testStartOrEndWithEscapedSpaces(self): + local = ' foo' + self.assertRaises(InvalidJID, JID, local=local, domain='example.com') + self.assertRaises(InvalidJID, JID, '%s@example.com' % local) + + local = 'bar ' + self.assertRaises(InvalidJID, JID, local=local, domain='example.com') + self.assertRaises(InvalidJID, JID, '%s@example.com' % local) + + # Need more input for these cases. A JID starting with \20 *is* valid + # according to RFC 6122, but is not according to XEP-0106. + #self.assertRaises(InvalidJID, JID, '%s@example.com' % '\\20foo2') + #self.assertRaises(InvalidJID, JID, '%s@example.com' % 'bar2\\20') + + def testNodePrepIdemptotent(self): + node = 'ᴹᴵᴷᴬᴱᴸ' + self.assertEqual(nodeprep(node), nodeprep(nodeprep(node))) + suite = unittest.TestLoader().loadTestsFromTestCase(TestJIDClass) diff --git a/tests/test_stanza_base.py b/tests/test_stanza_base.py index 9bd326b6..deb7ab96 100644 --- a/tests/test_stanza_base.py +++ b/tests/test_stanza_base.py @@ -1,4 +1,5 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.xmlstream.stanzabase import ET, StanzaBase diff --git a/tests/test_stanza_element.py b/tests/test_stanza_element.py index b7ccdb87..e678b56e 100644 --- a/tests/test_stanza_element.py +++ b/tests/test_stanza_element.py @@ -1,5 +1,6 @@ -from sleekxmpp.test import * -from sleekxmpp.xmlstream.stanzabase import ElementBase +import unittest +from sleekxmpp.test import SleekTest +from sleekxmpp.xmlstream.stanzabase import ElementBase, register_stanza_plugin, ET from sleekxmpp.thirdparty import OrderedDict @@ -384,7 +385,7 @@ class TestElementBase(SleekTest): interfaces = set(('bar', 'baz')) def setBar(self, value): - self._set_sub_text("path/to/only/bar", value); + self._set_sub_text("path/to/only/bar", value) def getBar(self): return self._get_sub_text("path/to/only/bar") @@ -393,7 +394,7 @@ class TestElementBase(SleekTest): self._del_sub("path/to/only/bar") def setBaz(self, value): - self._set_sub_text("path/to/just/baz", value); + self._set_sub_text("path/to/just/baz", value) def getBaz(self): return self._get_sub_text("path/to/just/baz") diff --git a/tests/test_stanza_error.py b/tests/test_stanza_error.py index a41bf4bf..d95a33ce 100644 --- a/tests/test_stanza_error.py +++ b/tests/test_stanza_error.py @@ -1,4 +1,5 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestErrorStanzas(SleekTest): diff --git a/tests/test_stanza_gmail.py b/tests/test_stanza_gmail.py index 6190c608..a15fea20 100644 --- a/tests/test_stanza_gmail.py +++ b/tests/test_stanza_gmail.py @@ -1,5 +1,8 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp import Iq +from sleekxmpp.test import SleekTest import sleekxmpp.plugins.gmail_notify as gmail +from sleekxmpp.xmlstream import register_stanza_plugin, ET class TestGmail(SleekTest): diff --git a/tests/test_stanza_iq.py b/tests/test_stanza_iq.py index 42e4dcde..0f5e30b0 100644 --- a/tests/test_stanza_iq.py +++ b/tests/test_stanza_iq.py @@ -1,4 +1,5 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.xmlstream.stanzabase import ET diff --git a/tests/test_stanza_message.py b/tests/test_stanza_message.py index e55971df..9968a630 100644 --- a/tests/test_stanza_message.py +++ b/tests/test_stanza_message.py @@ -1,6 +1,8 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.stanza.message import Message from sleekxmpp.stanza.htmlim import HTMLIM +from sleekxmpp.xmlstream import register_stanza_plugin class TestMessageStanzas(SleekTest): @@ -30,9 +32,7 @@ class TestMessageStanzas(SleekTest): msg['to'] = "fritzy@netflint.net/sleekxmpp" msg['body'] = "this is the plaintext message" msg['type'] = 'chat' - p = ET.Element('{http://www.w3.org/1999/xhtml}p') - p.text = "This is the htmlim message" - msg['html']['body'] = p + msg['html']['body'] = '<p>This is the htmlim message</p>' self.check(msg, """ <message to="fritzy@netflint.net/sleekxmpp" type="chat"> <body>this is the plaintext message</body> diff --git a/tests/test_stanza_presence.py b/tests/test_stanza_presence.py index 2ec43b65..184dce96 100644 --- a/tests/test_stanza_presence.py +++ b/tests/test_stanza_presence.py @@ -1,6 +1,6 @@ -from sleekxmpp.test import * -from sleekxmpp.stanza.presence import Presence - +import unittest +import sleekxmpp +from sleekxmpp.test import SleekTest class TestPresenceStanzas(SleekTest): diff --git a/tests/test_stanza_roster.py b/tests/test_stanza_roster.py index 8ec2d32b..d121568b 100644 --- a/tests/test_stanza_roster.py +++ b/tests/test_stanza_roster.py @@ -1,5 +1,6 @@ -from sleekxmpp.test import * -from sleekxmpp.stanza.roster import Roster +import unittest +from sleekxmpp.test import SleekTest +from sleekxmpp.xmlstream import ET class TestRosterStanzas(SleekTest): diff --git a/tests/test_stanza_xep_0004.py b/tests/test_stanza_xep_0004.py index e183e5e9..9056c663 100644 --- a/tests/test_stanza_xep_0004.py +++ b/tests/test_stanza_xep_0004.py @@ -1,7 +1,10 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp import Message +from sleekxmpp.test import SleekTest from sleekxmpp.thirdparty import OrderedDict import sleekxmpp.plugins.xep_0004 as xep_0004 +from sleekxmpp.xmlstream import register_stanza_plugin class TestDataForms(SleekTest): diff --git a/tests/test_stanza_xep_0030.py b/tests/test_stanza_xep_0030.py index 2d64988d..986c1880 100644 --- a/tests/test_stanza_xep_0030.py +++ b/tests/test_stanza_xep_0030.py @@ -1,5 +1,8 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp import Iq +from sleekxmpp.test import SleekTest import sleekxmpp.plugins.xep_0030 as xep_0030 +from sleekxmpp.xmlstream import register_stanza_plugin class TestDisco(SleekTest): diff --git a/tests/test_stanza_xep_0033.py b/tests/test_stanza_xep_0033.py index ec9a5309..bf10cf6c 100644 --- a/tests/test_stanza_xep_0033.py +++ b/tests/test_stanza_xep_0033.py @@ -1,5 +1,8 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp import Message +from sleekxmpp.test import SleekTest import sleekxmpp.plugins.xep_0033 as xep_0033 +from sleekxmpp.xmlstream import register_stanza_plugin class TestAddresses(SleekTest): diff --git a/tests/test_stanza_xep_0047.py b/tests/test_stanza_xep_0047.py index 6aa2314b..9fd3c4d6 100644 --- a/tests/test_stanza_xep_0047.py +++ b/tests/test_stanza_xep_0047.py @@ -1,5 +1,9 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.exceptions import XMPPError +from sleekxmpp import Iq +from sleekxmpp.test import SleekTest from sleekxmpp.plugins.xep_0047 import Data +from sleekxmpp.xmlstream import register_stanza_plugin, ET class TestIBB(SleekTest): diff --git a/tests/test_stanza_xep_0050.py b/tests/test_stanza_xep_0050.py index e02e86c3..9d49b3ee 100644 --- a/tests/test_stanza_xep_0050.py +++ b/tests/test_stanza_xep_0050.py @@ -1,6 +1,8 @@ from sleekxmpp import Iq -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.plugins.xep_0050 import Command +from sleekxmpp.xmlstream import register_stanza_plugin class TestAdHocCommandStanzas(SleekTest): diff --git a/tests/test_stanza_xep_0059.py b/tests/test_stanza_xep_0059.py index 913436a6..860ec869 100644 --- a/tests/test_stanza_xep_0059.py +++ b/tests/test_stanza_xep_0059.py @@ -1,5 +1,7 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.plugins.xep_0059 import Set +from sleekxmpp.xmlstream import ET class TestSetStanzas(SleekTest): diff --git a/tests/test_stanza_xep_0060.py b/tests/test_stanza_xep_0060.py index 16a7cb37..332b53ea 100644 --- a/tests/test_stanza_xep_0060.py +++ b/tests/test_stanza_xep_0060.py @@ -1,6 +1,8 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest import sleekxmpp.plugins.xep_0004 as xep_0004 import sleekxmpp.plugins.xep_0060.stanza as pubsub +from sleekxmpp.xmlstream.stanzabase import ET class TestPubsubStanzas(SleekTest): @@ -129,20 +131,6 @@ class TestPubsubStanzas(SleekTest): </pubsub> </iq>""") - def testState(self): - "Testing iq/psstate stanzas" - iq = self.Iq() - iq['psstate']['node']= 'mynode' - iq['psstate']['item']= 'myitem' - pl = ET.Element('{http://andyet.net/protocol/pubsubqueue}claimed') - iq['psstate']['payload'] = pl - self.check(iq, """ - <iq id="0"> - <state xmlns="http://jabber.org/protocol/psstate" node="mynode" item="myitem"> - <claimed xmlns="http://andyet.net/protocol/pubsubqueue" /> - </state> - </iq>""") - def testDefault(self): "Testing iq/pubsub_owner/default stanzas" iq = self.Iq() diff --git a/tests/test_stanza_xep_0085.py b/tests/test_stanza_xep_0085.py index 61784e47..303e6c5b 100644 --- a/tests/test_stanza_xep_0085.py +++ b/tests/test_stanza_xep_0085.py @@ -1,5 +1,9 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp import Message +from sleekxmpp.test import SleekTest import sleekxmpp.plugins.xep_0085 as xep_0085 +from sleekxmpp.xmlstream import register_stanza_plugin + class TestChatStates(SleekTest): diff --git a/tests/test_stanza_xep_0184.py b/tests/test_stanza_xep_0184.py index 13472373..0c340487 100644 --- a/tests/test_stanza_xep_0184.py +++ b/tests/test_stanza_xep_0184.py @@ -1,5 +1,8 @@ -from sleekxmpp.test import * +import unittest +from sleekxmpp import Message +from sleekxmpp.test import SleekTest import sleekxmpp.plugins.xep_0184 as xep_0184 +from sleekxmpp.xmlstream import register_stanza_plugin class TestReciept(SleekTest): diff --git a/tests/test_stanza_xep_0323.py b/tests/test_stanza_xep_0323.py new file mode 100644 index 00000000..7b1dfe42 --- /dev/null +++ b/tests/test_stanza_xep_0323.py @@ -0,0 +1,390 @@ +# -*- coding: utf-8 -*- + +from sleekxmpp.test import * +import sleekxmpp.plugins.xep_0323 as xep_0323 + +namespace='sn' + +class TestSensorDataStanzas(SleekTest): + + + def setUp(self): + pass + #register_stanza_plugin(Iq, xep_0323.stanza.Request) + #register_stanza_plugin(Iq, xep_0323.stanza.Accepted) + #register_stanza_plugin(Message, xep_0323.stanza.Failure) + #register_stanza_plugin(xep_0323.stanza.Failure, xep_0323.stanza.Error) + #register_stanza_plugin(Iq, xep_0323.stanza.Rejected) + #register_stanza_plugin(Message, xep_0323.stanza.Fields) + #register_stanza_plugin(Message, xep_0323.stanza.Request) + #register_stanza_plugin(Message, xep_0323.stanza.Accepted) + #register_stanza_plugin(Message, xep_0323.stanza.Failure) + # register_stanza_plugin(Message, xep_0323.stanza.Result) + # register_stanza_plugin(Message, xep_0323.stanza.Gone) + # register_stanza_plugin(Message, xep_0323.stanza.Inactive) + # register_stanza_plugin(Message, xep_0323.stanza.Paused) + + def testRequest(self): + """ + test of request stanza + """ + iq = self.Iq() + iq['type'] = 'get' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '1' + iq['req']['seqnr'] = '1' + iq['req']['momentary'] = 'true' + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'/> + </iq> + """ + ) + + def testRequestNodes(self): + """ + test of request nodes stanza + """ + iq = self.Iq() + iq['type'] = 'get' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '1' + iq['req']['seqnr'] = '1' + iq['req']['momentary'] = 'true' + + + iq['req'].add_node("Device02", "Source02", "CacheType") + iq['req'].add_node("Device44") + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'> + <node nodeId='Device02' sourceId='Source02' cacheType='CacheType'/> + <node nodeId='Device44'/> + </req> + </iq> + """ + ) + + iq['req'].del_node("Device02") + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'> + <node nodeId='Device44'/> + </req> + </iq> + """ + ) + + iq['req'].del_nodes() + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'> + </req> + </iq> + """ + ) + + def testRequestField(self): + """ + test of request field stanza + """ + iq = self.Iq() + iq['type'] = 'get' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '1' + iq['req']['seqnr'] = '1' + iq['req']['momentary'] = 'true' + + + iq['req'].add_field("Top temperature") + iq['req'].add_field("Bottom temperature") + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'> + <field name='Top temperature'/> + <field name='Bottom temperature'/> + </req> + </iq> + """ + ) + + iq['req'].del_field("Top temperature") + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'> + <field name='Bottom temperature'/> + </req> + </iq> + """ + ) + + iq['req'].del_fields() + + self.check(iq,""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'> + </req> + </iq> + """ + ) + + + def testAccepted(self): + """ + test of request stanza + """ + iq = self.Iq() + iq['type'] = 'result' + iq['from'] = 'device@clayster.com' + iq['to'] = 'master@clayster.com/amr' + iq['id'] = '2' + iq['accepted']['seqnr'] = '2' + + self.check(iq,""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='2'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='2'/> + </iq> + """ + ) + + def testRejected(self): + """ + test of request stanza + """ + iq = self.Iq() + iq['type'] = 'error' + iq['from'] = 'device@clayster.com' + iq['to'] = 'master@clayster.com/amr' + iq['id'] = '4' + iq['rejected']['seqnr'] = '4' + iq['rejected']['error'] = 'Access denied.' + + self.check(iq,""" + <iq type='error' + from='device@clayster.com' + to='master@clayster.com/amr' + id='4'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='4'> + <error>Access denied.</error> + </rejected> + </iq> + """ + ) + + def testFailure(self): + """ + test of failure stanza + """ + msg = self.Message() + msg['from'] = 'device@clayster.com' + msg['to'] = 'master@clayster.com/amr' + msg['failure']['seqnr'] = '3' + msg['failure']['done'] = 'true' + msg['failure']['error']['nodeId'] = 'Device01' + msg['failure']['error']['timestamp'] = '2013-03-07T17:13:30' + msg['failure']['error']['text'] = 'Timeout.' + + self.check(msg,""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <failure xmlns='urn:xmpp:iot:sensordata' seqnr='3' done='true'> + <error nodeId='Device01' timestamp='2013-03-07T17:13:30'> + Timeout.</error> + </failure> + </message> + """ + ) + + def testFields(self): + """ + test of fields stanza + """ + msg = self.Message() + msg['from'] = 'device@clayster.com' + msg['to'] = 'master@clayster.com/amr' + msg['fields']['seqnr'] = '1' + + node = msg['fields'].add_node("Device02") + ts = node.add_timestamp("2013-03-07T16:24:30") + + data = ts.add_data(typename="numeric", name="Temperature", value="-12.42", unit='K') + data['momentary'] = 'true' + data['automaticReadout'] = 'true' + + self.check(msg,""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId='Device02'> + <timestamp value='2013-03-07T16:24:30'> + <numeric name='Temperature' momentary='true' automaticReadout='true' value='-12.42' unit='K'/> + </timestamp> + </node> + </fields> + </message> + """ + ) + + node = msg['fields'].add_node("EmptyDevice") + node = msg['fields'].add_node("Device04") + ts = node.add_timestamp("EmptyTimestamp") + + self.check(msg,""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId='Device02'> + <timestamp value='2013-03-07T16:24:30'> + <numeric name='Temperature' momentary='true' automaticReadout='true' value='-12.42' unit='K'/> + </timestamp> + </node> + <node nodeId='EmptyDevice'/> + <node nodeId='Device04'> + <timestamp value='EmptyTimestamp'/> + </node> + </fields> + </message> + """ + ) + + node = msg['fields'].add_node("Device77") + ts = node.add_timestamp("2013-05-03T12:00:01") + data = ts.add_data(typename="numeric", name="Temperature", value="-12.42", unit='K') + data['historicalDay'] = 'true' + data = ts.add_data(typename="numeric", name="Speed", value="312.42", unit='km/h') + data['historicalWeek'] = 'false' + data = ts.add_data(typename="string", name="Temperature name", value="Bottom oil") + data['historicalMonth'] = 'true' + data = ts.add_data(typename="string", name="Speed name", value="Top speed") + data['historicalQuarter'] = 'false' + data = ts.add_data(typename="dateTime", name="T1", value="1979-01-01T00:00:00") + data['historicalYear'] = 'true' + data = ts.add_data(typename="dateTime", name="T2", value="2000-01-01T01:02:03") + data['historicalOther'] = 'false' + data = ts.add_data(typename="timeSpan", name="TS1", value="P5Y") + data['missing'] = 'true' + data = ts.add_data(typename="timeSpan", name="TS2", value="PT2M1S") + data['manualEstimate'] = 'false' + data = ts.add_data(typename="enum", name="top color", value="red", dataType="string") + data['invoiced'] = 'true' + data = ts.add_data(typename="enum", name="bottom color", value="black", dataType="string") + data['powerFailure'] = 'false' + data = ts.add_data(typename="boolean", name="Temperature real", value="false") + data['historicalDay'] = 'true' + data = ts.add_data(typename="boolean", name="Speed real", value="true") + data['historicalWeek'] = 'false' + + self.check(msg,""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId='Device02'> + <timestamp value='2013-03-07T16:24:30'> + <numeric name='Temperature' momentary='true' automaticReadout='true' value='-12.42' unit='K'/> + </timestamp> + </node> + <node nodeId='EmptyDevice'/> + <node nodeId='Device04'> + <timestamp value='EmptyTimestamp'/> + </node> + <node nodeId='Device77'> + <timestamp value='2013-05-03T12:00:01'> + <numeric name='Temperature' historicalDay='true' value='-12.42' unit='K'/> + <numeric name='Speed' historicalWeek='false' value='312.42' unit='km/h'/> + <string name='Temperature name' historicalMonth='true' value='Bottom oil'/> + <string name='Speed name' historicalQuarter='false' value='Top speed'/> + <dateTime name='T1' historicalYear='true' value='1979-01-01T00:00:00'/> + <dateTime name='T2' historicalOther='false' value='2000-01-01T01:02:03'/> + <timeSpan name='TS1' missing='true' value='P5Y'/> + <timeSpan name='TS2' manualEstimate='false' value='PT2M1S'/> + <enum name='top color' invoiced='true' value='red' dataType='string'/> + <enum name='bottom color' powerFailure='false' value='black' dataType='string'/> + <boolean name='Temperature real' historicalDay='true' value='false'/> + <boolean name='Speed real' historicalWeek='false' value='true'/> + </timestamp> + </node> + </fields> + </message> + """ + ) + + + def testTimestamp(self): + msg = self.Message() + + msg['from'] = 'device@clayster.com' + msg['to'] = 'master@clayster.com/amr' + msg['fields']['seqnr'] = '1' + + node = msg['fields'].add_node("Device02") + node = msg['fields'].add_node("Device03") + + ts = node.add_timestamp("2013-03-07T16:24:30") + ts = node.add_timestamp("2013-03-07T16:24:31") + + self.check(msg,""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId='Device02'/> + <node nodeId='Device03'> + <timestamp value='2013-03-07T16:24:30'/> + <timestamp value='2013-03-07T16:24:31'/> + </node> + </fields> + </message> + """ + ) + + + def testStringIdsMatcher(self): + """ + test of StringIds follow spec + """ + emptyStringIdXML='<message xmlns="jabber:client"><fields xmlns="urn:xmpp:iot:sensordata" /></message>' + + msg = self.Message() + msg['fields']['stringIds'] = "Nisse" + self.check(msg,emptyStringIdXML) + msg['fields']['stringIds'] = "Nisse___nje#" + self.check(msg,emptyStringIdXML) + msg['fields']['stringIds'] = "1" + self.check(msg,emptyStringIdXML) + + + + +suite = unittest.TestLoader().loadTestsFromTestCase(TestSensorDataStanzas) diff --git a/tests/test_stanza_xep_0325.py b/tests/test_stanza_xep_0325.py new file mode 100644 index 00000000..dc2e8efe --- /dev/null +++ b/tests/test_stanza_xep_0325.py @@ -0,0 +1,246 @@ +# -*- coding: utf-8 -*- +""" + SleekXMPP: The Sleek XMPP Library + Implementation of xeps for Internet of Things + http://wiki.xmpp.org/web/Tech_pages/IoT_systems + Copyright (C) 2013 Sustainable Innovation, Joachim.lindborg@sust.se, bjorn.westrom@consoden.se + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +from sleekxmpp.test import * +import sleekxmpp.plugins.xep_0325 as xep_0325 + +namespace='sn' + +class TestControlStanzas(SleekTest): + + + def setUp(self): + pass + + def testSetRequest(self): + """ + test of set request stanza + """ + iq = self.Iq() + iq['type'] = 'set' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '1' + iq['set'].add_node("Device02", "Source02", "MyCacheType") + iq['set'].add_node("Device15") + iq['set'].add_data("Tjohej", "boolean", "true") + + self.check(iq,""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device02' sourceId='Source02' cacheType='MyCacheType'/> + <node nodeId='Device15'/> + <boolean name='Tjohej' value='true'/> + </set> + </iq> + """ + ) + + iq['set'].del_node("Device02") + + self.check(iq,""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device15'/> + <boolean name='Tjohej' value='true'/> + </set> + </iq> + """ + ) + + iq['set'].del_nodes() + + self.check(iq,""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <boolean name='Tjohej' value='true'/> + </set> + </iq> + """ + ) + + + def testDirectSet(self): + """ + test of direct set stanza + """ + msg = self.Message() + msg['from'] = 'master@clayster.com/amr' + msg['to'] = 'device@clayster.com' + msg['set'].add_node("Device02") + msg['set'].add_node("Device15") + msg['set'].add_data("Tjohej", "boolean", "true") + + self.check(msg,""" + <message + from='master@clayster.com/amr' + to='device@clayster.com'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device02'/> + <node nodeId='Device15'/> + <boolean name='Tjohej' value='true'/> + </set> + </message> + """ + ) + + + def testSetResponse(self): + """ + test of set response stanza + """ + iq = self.Iq() + iq['type'] = 'result' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '8' + iq['setResponse']['responseCode'] = "OK" + + self.check(iq,""" + <iq type='result' + from='master@clayster.com/amr' + to='device@clayster.com' + id='8'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode='OK' /> + </iq> + """ + ) + + iq = self.Iq() + iq['type'] = 'error' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '9' + iq['setResponse']['responseCode'] = "OtherError" + iq['setResponse']['error']['var'] = "Output" + iq['setResponse']['error']['text'] = "Test of other error.!" + + self.check(iq,""" + <iq type='error' + from='master@clayster.com/amr' + to='device@clayster.com' + id='9'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode='OtherError'> + <error var='Output'>Test of other error.!</error> + </setResponse> + </iq> + """ + ) + + iq = self.Iq() + iq['type'] = 'error' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '9' + iq['setResponse']['responseCode'] = "NotFound" + iq['setResponse'].add_node("Device17", "Source09") + iq['setResponse'].add_node("Device18", "Source09") + iq['setResponse'].add_data("Tjohopp") + + self.check(iq,""" + <iq type='error' + from='master@clayster.com/amr' + to='device@clayster.com' + id='9'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode='NotFound'> + <node nodeId='Device17' sourceId='Source09'/> + <node nodeId='Device18' sourceId='Source09'/> + <parameter name='Tjohopp' /> + </setResponse> + </iq> + """ + ) + + def testSetRequestDatas(self): + """ + test of set request data stanzas + """ + iq = self.Iq() + iq['type'] = 'set' + iq['from'] = 'master@clayster.com/amr' + iq['to'] = 'device@clayster.com' + iq['id'] = '1' + iq['set'].add_node("Device02", "Source02", "MyCacheType") + iq['set'].add_node("Device15") + + iq['set'].add_data("Tjohej", "boolean", "true") + iq['set'].add_data("Tjohej2", "boolean", "false") + + iq['set'].add_data("TjohejC", "color", "FF00FF") + iq['set'].add_data("TjohejC2", "color", "00FF00") + + iq['set'].add_data("TjohejS", "string", "String1") + iq['set'].add_data("TjohejS2", "string", "String2") + + iq['set'].add_data("TjohejDate", "date", "2012-01-01") + iq['set'].add_data("TjohejDate2", "date", "1900-12-03") + + iq['set'].add_data("TjohejDateT4", "dateTime", "1900-12-03 12:30") + iq['set'].add_data("TjohejDateT2", "dateTime", "1900-12-03 11:22") + + iq['set'].add_data("TjohejDouble2", "double", "200.22") + iq['set'].add_data("TjohejDouble3", "double", "-12232131.3333") + + iq['set'].add_data("TjohejDur", "duration", "P5Y") + iq['set'].add_data("TjohejDur2", "duration", "PT2M1S") + + iq['set'].add_data("TjohejInt", "int", "1") + iq['set'].add_data("TjohejInt2", "int", "-42") + + iq['set'].add_data("TjohejLong", "long", "123456789098") + iq['set'].add_data("TjohejLong2", "long", "-90983243827489374") + + iq['set'].add_data("TjohejTime", "time", "23:59") + iq['set'].add_data("TjohejTime2", "time", "12:00") + + self.check(iq,""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device02' sourceId='Source02' cacheType='MyCacheType'/> + <node nodeId='Device15'/> + <boolean name='Tjohej' value='true'/> + <boolean name='Tjohej2' value='false'/> + <color name='TjohejC' value='FF00FF'/> + <color name='TjohejC2' value='00FF00'/> + <string name='TjohejS' value='String1'/> + <string name='TjohejS2' value='String2'/> + <date name='TjohejDate' value='2012-01-01'/> + <date name='TjohejDate2' value='1900-12-03'/> + <dateTime name='TjohejDateT4' value='1900-12-03 12:30'/> + <dateTime name='TjohejDateT2' value='1900-12-03 11:22'/> + <double name='TjohejDouble2' value='200.22'/> + <double name='TjohejDouble3' value='-12232131.3333'/> + <duration name='TjohejDur' value='P5Y'/> + <duration name='TjohejDur2' value='PT2M1S'/> + <int name='TjohejInt' value='1'/> + <int name='TjohejInt2' value='-42'/> + <long name='TjohejLong' value='123456789098'/> + <long name='TjohejLong2' value='-90983243827489374'/> + <time name='TjohejTime' value='23:59'/> + <time name='TjohejTime2' value='12:00'/> + </set> + </iq> + """ + ) + +suite = unittest.TestLoader().loadTestsFromTestCase(TestControlStanzas) diff --git a/tests/test_stream.py b/tests/test_stream.py index deac24a5..f68f8426 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -1,5 +1,6 @@ import time -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestStreamTester(SleekTest): diff --git a/tests/test_stream_exceptions.py b/tests/test_stream_exceptions.py index c41edbb2..d18d059a 100644 --- a/tests/test_stream_exceptions.py +++ b/tests/test_stream_exceptions.py @@ -1,9 +1,8 @@ -import sys -import sleekxmpp from sleekxmpp.xmlstream.matcher import MatchXPath from sleekxmpp.xmlstream.handler import Callback from sleekxmpp.exceptions import XMPPError -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestStreamExceptions(SleekTest): diff --git a/tests/test_stream_filters.py b/tests/test_stream_filters.py index ef4d5dc8..ee17ffdc 100644 --- a/tests/test_stream_filters.py +++ b/tests/test_stream_filters.py @@ -1,9 +1,8 @@ import time from sleekxmpp import Message -from sleekxmpp.test import * -from sleekxmpp.xmlstream.handler import * -from sleekxmpp.xmlstream.matcher import * +import unittest +from sleekxmpp.test import SleekTest class TestFilters(SleekTest): @@ -84,5 +83,5 @@ class TestFilters(SleekTest): """) - + suite = unittest.TestLoader().loadTestsFromTestCase(TestFilters) diff --git a/tests/test_stream_handlers.py b/tests/test_stream_handlers.py index 7fd4e648..0208cd16 100644 --- a/tests/test_stream_handlers.py +++ b/tests/test_stream_handlers.py @@ -1,9 +1,10 @@ import time +import threading -from sleekxmpp import Message -from sleekxmpp.test import * -from sleekxmpp.xmlstream.handler import * -from sleekxmpp.xmlstream.matcher import * +import unittest +from sleekxmpp.test import SleekTest +from sleekxmpp.exceptions import IqTimeout +from sleekxmpp import Callback, MatchXPath class TestHandlers(SleekTest): @@ -21,7 +22,7 @@ class TestHandlers(SleekTest): """Test using stream callback handlers.""" def callback_handler(stanza): - self.xmpp.sendRaw(""" + self.xmpp.send_raw(""" <message> <body>Success!</body> </message> @@ -31,7 +32,7 @@ class TestHandlers(SleekTest): MatchXPath('{test}tester'), callback_handler) - self.xmpp.registerHandler(callback) + self.xmpp.register_handler(callback) self.recv("""<tester xmlns="test" />""") @@ -49,7 +50,7 @@ class TestHandlers(SleekTest): iq['query'] = 'test' reply = iq.send(block=True) if reply: - self.xmpp.sendRaw(""" + self.xmpp.send_raw(""" <message> <body>Successful: %s</body> </message> @@ -112,7 +113,7 @@ class TestHandlers(SleekTest): time.sleep(0.1) # Check that the waiter is no longer registered - waiter_exists = self.xmpp.removeHandler('IqWait_test2') + waiter_exists = self.xmpp.remove_handler('IqWait_test2') self.failUnless(waiter_exists == False, "Waiter handler was not removed.") @@ -153,6 +154,35 @@ class TestHandlers(SleekTest): self.failUnless(events == ['foo'], "Iq callback was not executed: %s" % events) + def testIqTimeoutCallback(self): + """Test that iq.send(tcallback=handle_foo, timeout_callback=handle_timeout) works.""" + events = [] + + def handle_foo(iq): + events.append('foo') + + def handle_timeout(iq): + events.append('timeout') + + iq = self.Iq() + iq['type'] = 'get' + iq['id'] = 'test-foo' + iq['to'] = 'user@localhost' + iq['query'] = 'foo' + iq.send(callback=handle_foo, timeout_callback=handle_timeout, timeout=0.05) + + self.send(""" + <iq type="get" id="test-foo" to="user@localhost"> + <query xmlns="foo" /> + </iq> + """) + + # Give event queue time to process + time.sleep(1) + + self.failUnless(events == ['timeout'], + "Iq timeout was not executed: %s" % events) + def testMultipleHandlersForStanza(self): """ Test that multiple handlers for a single stanza work @@ -197,5 +227,57 @@ class TestHandlers(SleekTest): </message> """) + def testWrongSender(self): + """ + Test that using the wrong sender JID in a IQ result + doesn't trigger handlers. + """ + + events = [] + + def run_test(): + # Check that Iq was sent by waiter_handler + iq = self.Iq() + iq['id'] = 'test' + iq['to'] = 'tester@sleekxmpp.com/test' + iq['type'] = 'set' + iq['query'] = 'test' + result = iq.send() + events.append(result['from'].full) + + t = threading.Thread(name="sender_test", target=run_test) + t.start() + + self.recv(""" + <iq id="test" from="evil@sleekxmpp.com/bad" type="result"> + <query xmlns="test" /> + </iq> + """) + self.recv(""" + <iq id="test" from="evil2@sleekxmpp.com" type="result"> + <query xmlns="test" /> + </iq> + """) + self.recv(""" + <iq id="test" from="evil.com" type="result"> + <query xmlns="test" /> + </iq> + """) + + # Now for a good one + self.recv(""" + <iq id="test" from="tester@sleekxmpp.com/test" type="result"> + <query xmlns="test" /> + </iq> + """) + + t.join() + + time.sleep(0.1) + + self.assertEqual(events, ['tester@sleekxmpp.com/test'], "Did not timeout on bad sender") + + + suite = unittest.TestLoader().loadTestsFromTestCase(TestHandlers) diff --git a/tests/test_stream_presence.py b/tests/test_stream_presence.py index 4f2ede16..365a09ed 100644 --- a/tests/test_stream_presence.py +++ b/tests/test_stream_presence.py @@ -1,5 +1,6 @@ import time -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestStreamPresence(SleekTest): diff --git a/tests/test_stream_roster.py b/tests/test_stream_roster.py index 652ea1ce..221954ab 100644 --- a/tests/test_stream_roster.py +++ b/tests/test_stream_roster.py @@ -1,8 +1,9 @@ # -*- encoding:utf-8 -*- - from __future__ import unicode_literals -from sleekxmpp.test import * +import unittest +from sleekxmpp.exceptions import IqTimeout +from sleekxmpp.test import SleekTest import time import threading @@ -19,16 +20,9 @@ class TestStreamRoster(SleekTest): """Test handling roster requests.""" self.stream_start(mode='client', jid='tester@localhost') - events = [] - - def roster_received(iq): - events.append('roster_received') + roster_updates = [] - def roster_update(iq): - events.append('roster_update') - - self.xmpp.add_event_handler('roster_received', roster_received) - self.xmpp.add_event_handler('roster_update', roster_update) + self.xmpp.add_event_handler('roster_update', roster_updates.append) # Since get_roster blocks, we need to run it in a thread. t = threading.Thread(name='get_roster', target=self.xmpp.get_roster) @@ -56,6 +50,9 @@ class TestStreamRoster(SleekTest): # Wait for get_roster to return. t.join() + # Give the event queue time to process. + time.sleep(.1) + self.check_roster('tester@localhost', 'user@localhost', name='User', subscription='from', @@ -63,11 +60,8 @@ class TestStreamRoster(SleekTest): pending_out=True, groups=['Friends', 'Examples']) - # Give the event queue time to process. - time.sleep(.1) - - self.failUnless(events == ['roster_received', 'roster_update'], - "Wrong roster events fired: %s" % events) + self.failUnless(len(roster_updates) == 1, + "Wrong number of roster_update events fired: %s (should be 1)" % len(roster_updates)) def testRosterSet(self): """Test handling pushed roster updates.""" @@ -156,7 +150,7 @@ class TestStreamRoster(SleekTest): """Test rejecting a roster push from an unauthorized source.""" self.stream_start() self.recv(""" - <iq to='tester@localhost' from="malicious_user@localhost" + <iq to='tester@localhost' from="malicious_user@localhost" type="set" id="1"> <query xmlns="jabber:iq:roster"> <item jid="user@localhost" diff --git a/tests/test_stream_xep_0030.py b/tests/test_stream_xep_0030.py index dd43778a..37d29d33 100644 --- a/tests/test_stream_xep_0030.py +++ b/tests/test_stream_xep_0030.py @@ -1,8 +1,8 @@ -import sys import time import threading -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestStreamDisco(SleekTest): diff --git a/tests/test_stream_xep_0047.py b/tests/test_stream_xep_0047.py index d8cdd6a3..0515bca5 100644 --- a/tests/test_stream_xep_0047.py +++ b/tests/test_stream_xep_0047.py @@ -1,11 +1,12 @@ import threading import time -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestInBandByteStreams(SleekTest): - + def setUp(self): self.stream_start(plugins=['xep_0047', 'xep_0030']) @@ -13,7 +14,7 @@ class TestInBandByteStreams(SleekTest): self.stream_close() def testOpenStream(self): - """Test requesting a stream, successfully""" + """Test requesting a stream, successfully""" events = [] @@ -22,7 +23,7 @@ class TestInBandByteStreams(SleekTest): 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',), @@ -31,7 +32,7 @@ class TestInBandByteStreams(SleekTest): self.send(""" <iq type="set" to="tester@localhost/receiver" id="1"> - <open xmlns="http://jabber.org/protocol/ibb" + <open xmlns="http://jabber.org/protocol/ibb" sid="testing" block-size="4096" stanza="iq" /> @@ -62,18 +63,18 @@ class TestInBandByteStreams(SleekTest): 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', + 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" + <open xmlns="http://jabber.org/protocol/ibb" sid="testing" block-size="4096" stanza="iq" /> @@ -106,7 +107,7 @@ class TestInBandByteStreams(SleekTest): 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',), @@ -115,7 +116,7 @@ class TestInBandByteStreams(SleekTest): self.send(""" <iq type="set" to="tester@localhost/receiver" id="1"> - <open xmlns="http://jabber.org/protocol/ibb" + <open xmlns="http://jabber.org/protocol/ibb" sid="testing" block-size="4096" stanza="iq" /> @@ -142,8 +143,8 @@ class TestInBandByteStreams(SleekTest): <iq type="set" id="2" from="tester@localhost" to="tester@localhost/receiver"> - <data xmlns="http://jabber.org/protocol/ibb" - seq="0" + <data xmlns="http://jabber.org/protocol/ibb" + seq="0" sid="testing"> VGVzdGluZw== </data> @@ -161,8 +162,8 @@ class TestInBandByteStreams(SleekTest): <iq type="set" id="A" to="tester@localhost" from="tester@localhost/receiver"> - <data xmlns="http://jabber.org/protocol/ibb" - seq="0" + <data xmlns="http://jabber.org/protocol/ibb" + seq="0" sid="testing"> aXQgd29ya3Mh </data> @@ -174,7 +175,7 @@ class TestInBandByteStreams(SleekTest): to="tester@localhost/receiver" /> """) - self.assertEqual(data, ['it works!']) + self.assertEqual(data, [b'it works!']) suite = unittest.TestLoader().loadTestsFromTestCase(TestInBandByteStreams) diff --git a/tests/test_stream_xep_0050.py b/tests/test_stream_xep_0050.py index 5ad9d6ae..261a0057 100644 --- a/tests/test_stream_xep_0050.py +++ b/tests/test_stream_xep_0050.py @@ -1,8 +1,9 @@ import time import logging -import threading -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest +from sleekxmpp.xmlstream import ElementBase, register_stanza_plugin class TestAdHocCommands(SleekTest): @@ -35,7 +36,7 @@ class TestAdHocCommands(SleekTest): logging.debug(initial) new_payload = TestPayload() if initial: - new_payload['bar'] = 'Received: %s' % initial['bar'] + new_payload['bar'] = 'Received: %s' % initial['bar'] else: new_payload['bar'] = 'Failed' diff --git a/tests/test_stream_xep_0059.py b/tests/test_stream_xep_0059.py index 3a99842b..5f3ea079 100644 --- a/tests/test_stream_xep_0059.py +++ b/tests/test_stream_xep_0059.py @@ -1,6 +1,7 @@ import threading -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.xmlstream import register_stanza_plugin from sleekxmpp.plugins.xep_0030 import DiscoItems from sleekxmpp.plugins.xep_0059 import ResultIterator, Set @@ -17,7 +18,7 @@ class TestStreamSet(SleekTest): def iter(self, rev=False): q = self.xmpp.Iq() q['type'] = 'get' - it = ResultIterator(q, 'disco_items', '1', reverse=rev) + it = ResultIterator(q, 'disco_items', amount='1', reverse=rev) for i in it: for j in i['disco_items']['items']: self.items.append(j[0]) diff --git a/tests/test_stream_xep_0060.py b/tests/test_stream_xep_0060.py index e0936660..581d5d00 100644 --- a/tests/test_stream_xep_0060.py +++ b/tests/test_stream_xep_0060.py @@ -1,8 +1,7 @@ -import sys -import time import threading -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest from sleekxmpp.stanza.atom import AtomEntry from sleekxmpp.xmlstream import register_stanza_plugin @@ -431,7 +430,7 @@ class TestStreamPubsub(SleekTest): </publish> </pubsub> </iq> - """) + """, use_values=False) def testPublishSingleOptions(self): """Test publishing a single item, with options.""" diff --git a/tests/test_stream_xep_0066.py b/tests/test_stream_xep_0066.py index e3f2ddfa..175026d2 100644 --- a/tests/test_stream_xep_0066.py +++ b/tests/test_stream_xep_0066.py @@ -1,7 +1,7 @@ -import time import threading -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestOOB(SleekTest): diff --git a/tests/test_stream_xep_0085.py b/tests/test_stream_xep_0085.py index 2a814805..54e7e15f 100644 --- a/tests/test_stream_xep_0085.py +++ b/tests/test_stream_xep_0085.py @@ -1,7 +1,7 @@ -import threading import time -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestStreamChatStates(SleekTest): diff --git a/tests/test_stream_xep_0092.py b/tests/test_stream_xep_0092.py index 4a038558..c0748697 100644 --- a/tests/test_stream_xep_0092.py +++ b/tests/test_stream_xep_0092.py @@ -1,6 +1,7 @@ import threading -from sleekxmpp.test import * +import unittest +from sleekxmpp.test import SleekTest class TestStreamSet(SleekTest): @@ -36,7 +37,9 @@ class TestStreamSet(SleekTest): def query(): r = self.xmpp['xep_0092'].get_version('foo@bar') - results.append(r) + results.append((r['software_version']['name'], + r['software_version']['version'], + r['software_version']['os'])) self.stream_start(mode='client', plugins=['xep_0030', 'xep_0092']) @@ -61,7 +64,7 @@ class TestStreamSet(SleekTest): t.join() - expected = [{'name': 'Foo', 'version': '1.0', 'os':'Linux'}] + expected = [('Foo', '1.0', 'Linux')] self.assertEqual(results, expected, "Did not receive expected results: %s" % results) diff --git a/tests/test_stream_xep_0128.py b/tests/test_stream_xep_0128.py index 42fc9143..10222d9b 100644 --- a/tests/test_stream_xep_0128.py +++ b/tests/test_stream_xep_0128.py @@ -1,9 +1,5 @@ -import sys -import time -import threading - -from sleekxmpp.test import * -from sleekxmpp.xmlstream import ElementBase +import unittest +from sleekxmpp.test import SleekTest class TestStreamExtendedDisco(SleekTest): diff --git a/tests/test_stream_xep_0249.py b/tests/test_stream_xep_0249.py index 9a25253f..8edea270 100644 --- a/tests/test_stream_xep_0249.py +++ b/tests/test_stream_xep_0249.py @@ -1,9 +1,7 @@ -import sys import time -import threading -from sleekxmpp.test import * -from sleekxmpp.xmlstream import ElementBase +import unittest +from sleekxmpp.test import SleekTest class TestStreamDirectInvite(SleekTest): diff --git a/tests/test_stream_xep_0323.py b/tests/test_stream_xep_0323.py new file mode 100644 index 00000000..94f1d638 --- /dev/null +++ b/tests/test_stream_xep_0323.py @@ -0,0 +1,1250 @@ +# -*- coding: utf-8 -*- + +import sys +import datetime +import time +import threading + +from sleekxmpp.test import * +from sleekxmpp.xmlstream import ElementBase +from sleekxmpp.plugins.xep_0323.device import Device + + +class TestStreamSensorData(SleekTest): + + """ + Test using the XEP-0323 plugin. + """ + def setUp(self): + pass + + def _time_now(self): + return datetime.datetime.now().replace(microsecond=0).isoformat() + + def tearDown(self): + self.stream_close() + + def testRequestAccept(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device22") + myDevice._add_field(name="Temperature", typename="numeric", unit="°C") + myDevice._set_momentary_timestamp("2013-03-07T16:24:30") + myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"}) + + self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true'/> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'> + <node nodeId='Device22'> + <timestamp value='2013-03-07T16:24:30'> + <numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/> + </timestamp> + </node> + </fields> + </message> + """) + + def testRequestRejectAuth(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + self.xmpp['xep_0323']._set_authenticated("darth@deathstar.com") + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='4'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='5' momentary='true'/> + </iq> + """) + + self.send(""" + <iq type='error' + from='device@clayster.com' + to='master@clayster.com/amr' + id='4'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='5'> + <error>Access denied</error> + </rejected> + </iq> + """) + + def testRequestNode(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='77'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='66' momentary='true'> + <node nodeId='Device33'/> + </req> + </iq> + """) + + self.send(""" + <iq type='error' + from='device@clayster.com' + to='master@clayster.com/amr' + id='77'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='66'> + <error>Invalid nodeId Device33</error> + </rejected> + </iq> + """) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='8'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='7' momentary='true'> + <node nodeId='Device44'/> + </req> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='8'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/> + </iq> + """) + + + def testRequestField(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + myDevice._add_field(name='Voltage', typename="numeric", unit="V") + myDevice._add_field_timestamp_data(name="Voltage", value="230.4", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"}) + + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='7'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <field name='Current'/> + </req> + </iq> + """) + + self.send(""" + <iq type='error' + from='device@clayster.com' + to='master@clayster.com/amr' + id='7'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <error>Invalid field Current</error> + </rejected> + </iq> + """) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='8'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <field name='Voltage'/> + </req> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='8'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <node nodeId='Device44'> + <timestamp value='2000-01-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7' done='true'> + </fields> + </message> + """) + + def testRequestMultiTimestampSingleField(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + myDevice._add_field(name='Voltage', typename="numeric", unit="V") + myDevice._add_field_timestamp_data(name="Voltage", value="230.4", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field(name='Current', typename="numeric", unit="A") + myDevice._add_field(name='Height', typename="string") + myDevice._add_field_timestamp_data(name="Voltage", value="230.6", timestamp="2000-01-01T01:01:02") + myDevice._add_field_timestamp_data(name="Height", value="115 m", timestamp="2000-01-01T01:01:02", flags={"invoiced": "true"}) + + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='8'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <field name='Voltage'/> + </req> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='8'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <node nodeId='Device44'> + <timestamp value='2000-01-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <node nodeId='Device44'> + <timestamp value='2000-01-01T01:01:02'> + <numeric name='Voltage' value='230.6' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7' done='true'> + </fields> + </message> + """) + + def testRequestMultiTimestampAllFields(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + myDevice._add_field(name='Voltage', typename="numeric", unit="V") + myDevice._add_field_timestamp_data(name="Voltage", value="230.4", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field(name='Current', typename="numeric", unit="A") + myDevice._add_field(name='Height', typename="string") + myDevice._add_field_timestamp_data(name="Voltage", value="230.6", timestamp="2000-01-01T01:01:02") + myDevice._add_field_timestamp_data(name="Height", value="115 m", timestamp="2000-01-01T01:01:02", flags={"invoiced": "true"}) + + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='8'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='7'/> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='8'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='7'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <node nodeId='Device44'> + <timestamp value='2000-01-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7'> + <node nodeId='Device44'> + <timestamp value='2000-01-01T01:01:02'> + <numeric name='Voltage' value='230.6' unit='V'/> + <string name='Height' invoiced='true' value='115 m'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='7' done='true'> + </fields> + </message> + """) + + def testRequestAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", callback=None) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'/> + </iq> + """) + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=None) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='2'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='2'> + <node nodeId="Device33"/> + <node nodeId="Device22"/> + </req> + </iq> + """) + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", fields=['Temperature', 'Voltage'], callback=None) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='3'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='3'> + <field name="Temperature"/> + <field name="Voltage"/> + </req> + </iq> + """) + + def testRequestRejectAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + results = [] + + def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None): + if (result == "rejected") and (error_msg == "Invalid device Device22"): + results.append("rejected") + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=my_callback) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId="Device33"/> + <node nodeId="Device22"/> + </req> + </iq> + """) + + self.recv(""" + <iq type='error' + from='you@google.com' + to='tester@localhost' + id='1'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <error>Invalid device Device22</error> + </rejected> + </iq> + """) + + time.sleep(.1) + + self.failUnless(results == ["rejected"], + "Rejected callback was not properly executed") + + def testRequestAcceptedAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + results = [] + + def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None): + results.append(result) + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=my_callback) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId="Device33"/> + <node nodeId="Device22"/> + </req> + </iq> + """) + + self.recv(""" + <iq type='result' + from='you@google.com' + to='tester@localhost' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/> + </iq> + """) + + time.sleep(.1) + + self.failUnless(results == ["accepted"], + "Accepted callback was not properly executed") + + def testRequestFieldsAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + results = [] + callback_data = {} + + def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None): + results.append(result) + if result == "fields": + callback_data["nodeId"] = nodeId + callback_data["timestamp"] = timestamp + callback_data["error_msg"] = error_msg + for f in fields: + callback_data["field_" + f['name']] = f + + t1= threading.Thread(name="request_data", + target=self.xmpp['xep_0323'].request_data, + kwargs={"from_jid": "tester@localhost", + "to_jid": "you@google.com", + "nodeIds": ['Device33'], + "callback": my_callback}) + t1.start() + #self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33'], callback=my_callback); + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId="Device33"/> + </req> + </iq> + """) + + self.recv(""" + <iq type='result' + from='you@google.com' + to='tester@localhost' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/> + </iq> + """) + + self.recv(""" + <message from='you@google.com' + to='tester@localhost'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId='Device33'> + <timestamp value='2000-01-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/> + <boolean name='TestBool' value='true'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.recv(""" + <message from='you@google.com' + to='tester@localhost'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'/> + </message> + """) + + t1.join() + time.sleep(.5) + + self.failUnlessEqual(results, ["accepted","fields","done"]) + # self.assertIn("nodeId", callback_data); + self.assertTrue("nodeId" in callback_data) + self.failUnlessEqual(callback_data["nodeId"], "Device33") + # self.assertIn("timestamp", callback_data); + self.assertTrue("timestamp" in callback_data) + self.failUnlessEqual(callback_data["timestamp"], "2000-01-01T00:01:02") + #self.assertIn("field_Voltage", callback_data); + self.assertTrue("field_Voltage" in callback_data) + self.failUnlessEqual(callback_data["field_Voltage"], {"name": "Voltage", "value": "230.4", "typename": "numeric", "unit": "V", "flags": {"invoiced": "true"}}) + #self.assertIn("field_TestBool", callback_data); + self.assertTrue("field_TestBool" in callback_data) + self.failUnlessEqual(callback_data["field_TestBool"], {"name": "TestBool", "value": "true", "typename": "boolean" }) + + def testServiceDiscoveryClient(self): + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='tester@localhost' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + """) + + self.send(""" + <iq type='result' + to='master@clayster.com/amr' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'> + <identity category='client' type='bot'/> + <feature var='urn:xmpp:iot:sensordata'/> + </query> + </iq> + """) + + def testServiceDiscoveryComponent(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='tester@localhost' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + """) + + self.send(""" + <iq type='result' + from='tester@localhost' + to='master@clayster.com/amr' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'> + <identity category='component' type='generic'/> + <feature var='urn:xmpp:iot:sensordata'/> + </query> + </iq> + """) + + def testRequestTimeout(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + results = [] + callback_data = {} + + def my_callback(from_jid, result, nodeId=None, timestamp=None, error_msg=None): + results.append(result) + if result == "failure": + callback_data["nodeId"] = nodeId + callback_data["timestamp"] = timestamp + callback_data["error_msg"] = error_msg + + t1= threading.Thread(name="request_data", + target=self.xmpp['xep_0323'].request_data, + kwargs={"from_jid": "tester@localhost", + "to_jid": "you@google.com", + "nodeIds": ['Device33'], + "callback": my_callback}) + t1.start() + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId="Device33"/> + </req> + </iq> + """) + + self.recv(""" + <iq type='result' + from='you@google.com' + to='tester@localhost' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/> + </iq> + """) + + self.recv(""" + <message from='you@google.com' + to='tester@localhost'> + <failure xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'> + <error nodeId='Device33' timestamp='2013-03-07T17:13:30'>Timeout.</error> + </failure> + </message> + """) + + t1.join() + time.sleep(.5) + + self.failUnlessEqual(results, ["accepted","failure"]) + # self.assertIn("nodeId", callback_data); + self.assertTrue("nodeId" in callback_data) + self.failUnlessEqual(callback_data["nodeId"], "Device33") + # self.assertIn("timestamp", callback_data); + self.assertTrue("timestamp" in callback_data) + self.failUnlessEqual(callback_data["timestamp"], "2013-03-07T17:13:30") + # self.assertIn("error_msg", callback_data); + self.assertTrue("error_msg" in callback_data) + self.failUnlessEqual(callback_data["error_msg"], "Timeout.") + + def testDelayedRequest(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device22") + myDevice._add_field(name="Temperature", typename="numeric", unit="°C") + myDevice._set_momentary_timestamp("2013-03-07T16:24:30") + myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"}) + + self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + dtnow = datetime.datetime.now() + ts_2sec = datetime.timedelta(0,2) + dtnow_plus_2sec = dtnow + ts_2sec + when_flag = dtnow_plus_2sec.replace(microsecond=0).isoformat() + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true' when='""" + when_flag + """'/> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1' queued='true' /> + </iq> + """) + + time.sleep(2) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <started xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'> + <node nodeId='Device22'> + <timestamp value='2013-03-07T16:24:30'> + <numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/> + </timestamp> + </node> + </fields> + </message> + """) + + def testDelayedRequestFail(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device22") + myDevice._add_field(name="Temperature", typename="numeric", unit="°C") + myDevice._set_momentary_timestamp("2013-03-07T16:24:30") + myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"}) + + self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + dtnow = datetime.datetime.now() + ts_2sec = datetime.timedelta(0,2) + dtnow_minus_2sec = dtnow - ts_2sec + when_flag = dtnow_minus_2sec.replace(microsecond=0).isoformat() + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true' when='""" + when_flag + """'/> + </iq> + """) + + # Remove the returned datetime to allow predictable test + xml_stanza = self._filtered_stanza_prepare() + error_text = xml_stanza['rejected']['error'] #['text'] + error_text = error_text[:error_text.find(':')] + xml_stanza['rejected']['error'] = error_text + + self._filtered_stanza_check(""" + <iq type='error' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <error>Invalid datetime in 'when' flag, cannot set a time in the past. Current time</error> + </rejected> + </iq> + """, xml_stanza) + + + def _filtered_stanza_prepare(self, timeout=.5): + sent = self.xmpp.socket.next_sent(timeout) + if sent is None: + self.fail("No stanza was sent.") + + xml = self.parse_xml(sent) + self.fix_namespaces(xml, 'jabber:client') + sent = self.xmpp._build_stanza(xml, 'jabber:client') + return sent + + def _filtered_stanza_check(self, data, filtered, defaults=None, use_values=True, method='exact'): + self.check(filtered, data, + method=method, + defaults=defaults, + use_values=use_values) + + def testRequestFieldFrom(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + myDevice._add_field(name='Voltage', typename="numeric", unit="V") + myDevice._add_field_timestamp_data(name="Voltage", value="230.1", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field_timestamp_data(name="Voltage", value="230.2", timestamp="2000-02-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field_timestamp_data(name="Voltage", value="230.3", timestamp="2000-03-01T00:01:02", flags={"invoiced": "true"}) + + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='6'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='6' from='2000-01-02T00:00:01'> + <field name='Voltage'/> + </req> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='6'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='6'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <node nodeId='Device44'> + <timestamp value='2000-02-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.2' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <node nodeId='Device44'> + <timestamp value='2000-03-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.3' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6' done='true'> + </fields> + </message> + """) + + def testRequestFieldTo(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + myDevice._add_field(name='Voltage', typename="numeric", unit="V") + myDevice._add_field_timestamp_data(name="Voltage", value="230.1", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field_timestamp_data(name="Voltage", value="230.2", timestamp="2000-02-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field_timestamp_data(name="Voltage", value="230.3", timestamp="2000-03-01T00:01:02", flags={"invoiced": "true"}) + + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='6'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='6' to='2000-02-02T00:00:01'> + <field name='Voltage'/> + </req> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='6'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='6'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <node nodeId='Device44'> + <timestamp value='2000-01-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.1' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <node nodeId='Device44'> + <timestamp value='2000-02-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.2' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6' done='true'> + </fields> + </message> + """) + + def testRequestFieldFromTo(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device44") + myDevice._add_field(name='Voltage', typename="numeric", unit="V") + myDevice._add_field_timestamp_data(name="Voltage", value="230.1", timestamp="2000-01-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field_timestamp_data(name="Voltage", value="230.2", timestamp="2000-02-01T00:01:02", flags={"invoiced": "true"}) + myDevice._add_field_timestamp_data(name="Voltage", value="230.3", timestamp="2000-03-01T00:01:02", flags={"invoiced": "true"}) + + self.xmpp['xep_0323'].register_node('Device44', myDevice, commTimeout=0.5) + + print("."), + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='6'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='6' from='2000-01-01T00:01:03' to='2000-02-02T00:00:01'> + <field name='Voltage'/> + </req> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='6'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='6'/> + </iq> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6'> + <node nodeId='Device44'> + <timestamp value='2000-02-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.2' unit='V'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.send(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='6' done='true'> + </fields> + </message> + """) + + def testDelayedRequestClient(self): + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + results = [] + callback_data = {} + + def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None): + results.append(result) + if result == "fields": + callback_data["nodeId"] = nodeId + callback_data["timestamp"] = timestamp + callback_data["error_msg"] = error_msg + for f in fields: + callback_data["field_" + f['name']] = f + + t1= threading.Thread(name="request_data", + target=self.xmpp['xep_0323'].request_data, + kwargs={"from_jid": "tester@localhost", + "to_jid": "you@google.com", + "nodeIds": ['Device33'], + "callback": my_callback}) + t1.start() + #self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33'], callback=my_callback); + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId="Device33"/> + </req> + </iq> + """) + + self.recv(""" + <iq type='result' + from='you@google.com' + to='tester@localhost' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1' queued='true'/> + </iq> + """) + + self.recv(""" + <message from='device@clayster.com' + to='master@clayster.com/amr'> + <started xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </message> + """) + + self.recv(""" + <message from='you@google.com' + to='tester@localhost'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId='Device33'> + <timestamp value='2000-01-01T00:01:02'> + <numeric name='Voltage' invoiced='true' value='230.4' unit='V'/> + <boolean name='TestBool' value='true'/> + </timestamp> + </node> + </fields> + </message> + """) + + self.recv(""" + <message from='you@google.com' + to='tester@localhost'> + <fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'/> + </message> + """) + + t1.join() + time.sleep(.5) + + self.failUnlessEqual(results, ["queued","started","fields","done"]) + # self.assertIn("nodeId", callback_data); + self.assertTrue("nodeId" in callback_data) + self.failUnlessEqual(callback_data["nodeId"], "Device33") + # self.assertIn("timestamp", callback_data); + self.assertTrue("timestamp" in callback_data) + self.failUnlessEqual(callback_data["timestamp"], "2000-01-01T00:01:02") + # self.assertIn("field_Voltage", callback_data); + self.assertTrue("field_Voltage" in callback_data) + self.failUnlessEqual(callback_data["field_Voltage"], {"name": "Voltage", "value": "230.4", "typename": "numeric", "unit": "V", "flags": {"invoiced": "true"}}) + # self.assertIn("field_TestBool", callback_data); + self.assertTrue("field_TestBool" in callback_data) + self.failUnlessEqual(callback_data["field_TestBool"], {"name": "TestBool", "value": "true", "typename": "boolean" }) + + + def testRequestFieldsCancelAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0323']) + + results = [] + + def my_callback(from_jid, result, nodeId=None, timestamp=None, fields=None, error_msg=None): + results.append(result) + + session = self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33'], callback=my_callback) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <node nodeId="Device33"/> + </req> + </iq> + """) + + self.recv(""" + <iq type='result' + from='you@google.com' + to='tester@localhost' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1'/> + </iq> + """) + + self.xmpp['xep_0323'].cancel_request(session=session) + + self.send(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <cancel xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </iq> + """) + + self.recv(""" + <iq type='result' + from='tester@localhost' + to='you@google.com' + id='1'> + <cancelled xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </iq> + """) + + time.sleep(.5) + + self.failUnlessEqual(results, ["accepted","cancelled"]) + + def testDelayedRequestCancel(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + myDevice = Device("Device22") + myDevice._add_field(name="Temperature", typename="numeric", unit="°C") + myDevice._set_momentary_timestamp("2013-03-07T16:24:30") + myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"}) + + self.xmpp['xep_0323'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + dtnow = datetime.datetime.now() + ts_2sec = datetime.timedelta(0,2) + dtnow_plus_2sec = dtnow + ts_2sec + when_flag = dtnow_plus_2sec.replace(microsecond=0).isoformat() + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <req xmlns='urn:xmpp:iot:sensordata' seqnr='1' momentary='true' when='""" + when_flag + """'/> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <accepted xmlns='urn:xmpp:iot:sensordata' seqnr='1' queued='true' /> + </iq> + """) + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <cancel xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <cancelled xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </iq> + """) + + # Test cancel of non-existing request + self.recv(""" + <iq type='get' + from='tester@localhost' + to='you@google.com' + id='1'> + <cancel xmlns='urn:xmpp:iot:sensordata' seqnr='1' /> + </iq> + """) + + self.send(""" + <iq type='error' + from='you@google.com' + to='tester@localhost' + id='1'> + <rejected xmlns='urn:xmpp:iot:sensordata' seqnr='1'> + <error>Cancel request received, no matching request is active.</error> + </rejected> + </iq> + """) + + time.sleep(2) + + # Ensure we don't get anything after cancellation + self.send(None) + + + +suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamSensorData) + diff --git a/tests/test_stream_xep_0325.py b/tests/test_stream_xep_0325.py new file mode 100644 index 00000000..2ebdd121 --- /dev/null +++ b/tests/test_stream_xep_0325.py @@ -0,0 +1,365 @@ +# -*- coding: utf-8 -*- +""" + SleekXMPP: The Sleek XMPP Library + Implementation of xeps for Internet of Things + http://wiki.xmpp.org/web/Tech_pages/IoT_systems + Copyright (C) 2013 Sustainable Innovation, Joachim.lindborg@sust.se, bjorn.westrom@consoden.se + This file is part of SleekXMPP. + + See the file LICENSE for copying permission. +""" + +import sys +import datetime +import time +import threading + +from sleekxmpp.test import * +from sleekxmpp.xmlstream import ElementBase +from sleekxmpp.plugins.xep_0325.device import Device + + +class TestStreamControl(SleekTest): + + """ + Test using the XEP-0325 plugin. + """ + def setUp(self): + pass + + def _time_now(self): + return datetime.datetime.now().replace(microsecond=0).isoformat() + + def tearDown(self): + self.stream_close() + + def testRequestSetOk(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0325']) + + myDevice = Device("Device22") + myDevice._add_control_field(name="Temperature", typename="int", value="15") + + self.xmpp['xep_0325'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + self.recv(""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <int name="Temperature" value="17"/> + </set> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode="OK" /> + </iq> + """) + + self.assertEqual(myDevice._get_field_value("Temperature"), "17") + + def testRequestSetMulti(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0325']) + + myDevice = Device("Device22") + myDevice._add_control_field(name="Temperature", typename="int", value="15") + myDevice._add_control_field(name="Startup", typename="date", value="2013-01-03") + + myDevice2 = Device("Device23") + myDevice2._add_control_field(name="Temperature", typename="int", value="19") + myDevice2._add_control_field(name="Startup", typename="date", value="2013-01-09") + + self.xmpp['xep_0325'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + self.xmpp['xep_0325'].register_node(nodeId="Device23", device=myDevice2, commTimeout=0.5) + + self.recv(""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device22' /> + <int name="Temperature" value="17"/> + </set> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='1'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode="OK" /> + </iq> + """) + + self.assertEqual(myDevice._get_field_value("Temperature"), "17") + self.assertEqual(myDevice2._get_field_value("Temperature"), "19") + + self.recv(""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='2'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device23' /> + <node nodeId='Device22' /> + <date name="Startup" value="2013-02-01"/> + <int name="Temperature" value="20"/> + </set> + </iq> + """) + + self.send(""" + <iq type='result' + from='device@clayster.com' + to='master@clayster.com/amr' + id='2'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode="OK" /> + </iq> + """) + + self.assertEqual(myDevice._get_field_value("Temperature"), "20") + self.assertEqual(myDevice2._get_field_value("Temperature"), "20") + self.assertEqual(myDevice._get_field_value("Startup"), "2013-02-01") + self.assertEqual(myDevice2._get_field_value("Startup"), "2013-02-01") + + def testRequestSetFail(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0325']) + + myDevice = Device("Device23") + myDevice._add_control_field(name="Temperature", typename="int", value="15") + + self.xmpp['xep_0325'].register_node(nodeId="Device23", device=myDevice, commTimeout=0.5) + + self.recv(""" + <iq type='set' + from='master@clayster.com/amr' + to='device@clayster.com' + id='9'> + <set xmlns='urn:xmpp:iot:control'> + <int name="Voltage" value="17"/> + </set> + </iq> + """) + + self.send(""" + <iq type='error' + from='device@clayster.com' + to='master@clayster.com/amr' + id='9'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode='NotFound'> + <parameter name='Voltage' /> + <error var='Output'>Invalid field Voltage</error> + </setResponse> + </iq> + """) + + self.assertEqual(myDevice._get_field_value("Temperature"), "15") + self.assertFalse(myDevice.has_control_field("Voltage", "int")) + + def testDirectSetOk(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0325']) + + myDevice = Device("Device22") + myDevice._add_control_field(name="Temperature", typename="int", value="15") + + self.xmpp['xep_0325'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + self.recv(""" + <message + from='master@clayster.com/amr' + to='device@clayster.com'> + <set xmlns='urn:xmpp:iot:control'> + <int name="Temperature" value="17"/> + </set> + </message> + """) + + time.sleep(.5) + + self.assertEqual(myDevice._get_field_value("Temperature"), "17") + + def testDirectSetFail(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0325']) + + myDevice = Device("Device22") + myDevice._add_control_field(name="Temperature", typename="int", value="15") + + self.xmpp['xep_0325'].register_node(nodeId="Device22", device=myDevice, commTimeout=0.5) + + self.recv(""" + <message + from='master@clayster.com/amr' + to='device@clayster.com'> + <set xmlns='urn:xmpp:iot:control'> + <int name="Voltage" value="17"/> + </set> + </message> + """) + + time.sleep(.5) + + self.assertEqual(myDevice._get_field_value("Temperature"), "15") + self.assertFalse(myDevice.has_control_field("Voltage", "int")) + + + def testRequestSetOkAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0325']) + + results = [] + + def my_callback(from_jid, result, nodeIds=None, fields=None, error_msg=None): + results.append(result) + + fields = [] + fields.append(("Temperature", "double", "20.5")) + fields.append(("TemperatureAlarmSetting", "string", "High")) + + self.xmpp['xep_0325'].set_request(from_jid="tester@localhost", to_jid="you@google.com", fields=fields, nodeIds=['Device33', 'Device22'], callback=my_callback) + + self.send(""" + <iq type='set' + from='tester@localhost' + to='you@google.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device33' /> + <node nodeId='Device22' /> + <double name="Temperature" value="20.5" /> + <string name="TemperatureAlarmSetting" value="High" /> + </set> + </iq> + """) + + self.recv(""" + <iq type='result' + from='you@google.com' + to='tester@localhost' + id='1'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode="OK" /> + </iq> + """) + + time.sleep(.5) + + self.assertEqual(results, ["OK"]) + + def testRequestSetErrorAPI(self): + + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0325']) + + results = [] + + def my_callback(from_jid, result, nodeIds=None, fields=None, error_msg=None): + results.append(result) + + fields = [] + fields.append(("Temperature", "double", "20.5")) + fields.append(("TemperatureAlarmSetting", "string", "High")) + + self.xmpp['xep_0325'].set_request(from_jid="tester@localhost", to_jid="you@google.com", fields=fields, nodeIds=['Device33', 'Device22'], callback=my_callback) + + self.send(""" + <iq type='set' + from='tester@localhost' + to='you@google.com' + id='1'> + <set xmlns='urn:xmpp:iot:control'> + <node nodeId='Device33' /> + <node nodeId='Device22' /> + <double name="Temperature" value="20.5" /> + <string name="TemperatureAlarmSetting" value="High" /> + </set> + </iq> + """) + + self.recv(""" + <iq type='error' + from='you@google.com' + to='tester@localhost' + id='1'> + <setResponse xmlns='urn:xmpp:iot:control' responseCode="OtherError" > + <error var='Temperature'>Sensor error</error> + </setResponse> + </iq> + """) + + time.sleep(.5) + + self.assertEqual(results, ["OtherError"]) + + def testServiceDiscoveryClient(self): + self.stream_start(mode='client', + plugins=['xep_0030', + 'xep_0325']) + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='tester@localhost' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + """) + + self.send(""" + <iq type='result' + to='master@clayster.com/amr' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'> + <identity category='client' type='bot'/> + <feature var='urn:xmpp:iot:control'/> + </query> + </iq> + """) + + def testServiceDiscoveryComponent(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0325']) + + self.recv(""" + <iq type='get' + from='master@clayster.com/amr' + to='tester@localhost' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'/> + </iq> + """) + + self.send(""" + <iq type='result' + from='tester@localhost' + to='master@clayster.com/amr' + id='disco1'> + <query xmlns='http://jabber.org/protocol/disco#info'> + <identity category='component' type='generic'/> + <feature var='urn:xmpp:iot:control'/> + </query> + </iq> + """) + + +suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamControl) + diff --git a/tests/test_tostring.py b/tests/test_tostring.py index e456d28e..e6148533 100644 --- a/tests/test_tostring.py +++ b/tests/test_tostring.py @@ -1,7 +1,7 @@ -from sleekxmpp.test import * -from sleekxmpp.stanza import Message -from sleekxmpp.xmlstream.stanzabase import ET, ElementBase -from sleekxmpp.xmlstream.tostring import tostring, xml_escape +import unittest +from sleekxmpp.test import SleekTest +from sleekxmpp.xmlstream.stanzabase import ET +from sleekxmpp.xmlstream.tostring import tostring, escape class TestToString(SleekTest): @@ -30,7 +30,7 @@ class TestToString(SleekTest): def testXMLEscape(self): """Test escaping XML special characters.""" original = """<foo bar="baz">'Hi & welcome!'</foo>""" - escaped = xml_escape(original) + escaped = escape(original) desired = """<foo bar="baz">'Hi""" desired += """ & welcome!'</foo>""" @@ -85,19 +85,6 @@ class TestToString(SleekTest): original='<a>foo <b>bar</b> baz</a>', message='Element tail content is incorrect.') - - def testStanzaNs(self): - """ - Test using the stanza_ns tostring parameter, which will prevent - adding an xmlns attribute to the serialized element if the - element's namespace is the same. - """ - self.tryTostring( - original='<bar xmlns="foo" />', - expected='<bar />', - message="The stanza_ns parameter was not used properly.", - stanza_ns='foo') - def testStanzaStr(self): """ Test that stanza objects are serialized properly. |