summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_events.py3
-rw-r--r--tests/test_jid.py153
-rw-r--r--tests/test_stanza_base.py3
-rw-r--r--tests/test_stanza_element.py9
-rw-r--r--tests/test_stanza_error.py3
-rw-r--r--tests/test_stanza_gmail.py5
-rw-r--r--tests/test_stanza_iq.py3
-rw-r--r--tests/test_stanza_message.py8
-rw-r--r--tests/test_stanza_presence.py6
-rw-r--r--tests/test_stanza_roster.py5
-rw-r--r--tests/test_stanza_xep_0004.py5
-rw-r--r--tests/test_stanza_xep_0030.py5
-rw-r--r--tests/test_stanza_xep_0033.py5
-rw-r--r--tests/test_stanza_xep_0047.py6
-rw-r--r--tests/test_stanza_xep_0050.py4
-rw-r--r--tests/test_stanza_xep_0059.py4
-rw-r--r--tests/test_stanza_xep_0060.py18
-rw-r--r--tests/test_stanza_xep_0085.py6
-rw-r--r--tests/test_stanza_xep_0184.py5
-rw-r--r--tests/test_stanza_xep_0323.py390
-rw-r--r--tests/test_stanza_xep_0325.py246
-rw-r--r--tests/test_stream.py3
-rw-r--r--tests/test_stream_exceptions.py5
-rw-r--r--tests/test_stream_filters.py7
-rw-r--r--tests/test_stream_handlers.py98
-rw-r--r--tests/test_stream_presence.py3
-rw-r--r--tests/test_stream_roster.py28
-rw-r--r--tests/test_stream_xep_0030.py4
-rw-r--r--tests/test_stream_xep_0047.py31
-rw-r--r--tests/test_stream_xep_0050.py7
-rw-r--r--tests/test_stream_xep_0059.py5
-rw-r--r--tests/test_stream_xep_0060.py7
-rw-r--r--tests/test_stream_xep_0066.py4
-rw-r--r--tests/test_stream_xep_0085.py4
-rw-r--r--tests/test_stream_xep_0092.py9
-rw-r--r--tests/test_stream_xep_0128.py8
-rw-r--r--tests/test_stream_xep_0249.py6
-rw-r--r--tests/test_stream_xep_0323.py1250
-rw-r--r--tests/test_stream_xep_0325.py365
-rw-r--r--tests/test_tostring.py23
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 = """&lt;foo bar=&quot;baz&quot;&gt;&apos;Hi"""
desired += """ &amp; welcome!&apos;&lt;/foo&gt;"""
@@ -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.