From 45689fd8799186fd6be0b308745aef428ab50dcc Mon Sep 17 00:00:00 2001 From: Joachim Lindborg Date: Fri, 30 Aug 2013 02:29:52 +0200 Subject: First implementation of the xep_0323 and xep_325 used in IoT systems. Tests are added for stanza and streams --- tests/test_stream_xep_0323.py | 1250 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1250 insertions(+) create mode 100644 tests/test_stream_xep_0323.py (limited to 'tests/test_stream_xep_0323.py') diff --git a/tests/test_stream_xep_0323.py b/tests/test_stream_xep_0323.py new file mode 100644 index 00000000..b10f0b0d --- /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(""" + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + def testRequestRejectAuth(self): + + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']) + + self.xmpp['xep_0323']._set_authenticated("darth@deathstar.com"); + + self.recv(""" + + + + """) + + self.send(""" + + + Access denied + + + """) + + 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(""" + + + + + + """) + + self.send(""" + + + Invalid nodeId Device33 + + + """) + + print("."), + + self.recv(""" + + + + + + """) + + self.send(""" + + + + """) + + + 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(""" + + + + + + """) + + self.send(""" + + + Invalid field Current + + + """) + + print("."), + + self.recv(""" + + + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + """) + + 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(""" + + + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + """) + + 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(""" + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + + + + + + + """) + + self.send(""" + + + + + """) + + 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(""" + + + + """) + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", nodeIds=['Device33', 'Device22'], callback=None); + + self.send(""" + + + + + + + """) + + self.xmpp['xep_0323'].request_data(from_jid="tester@localhost", to_jid="you@google.com", fields=['Temperature', 'Voltage'], callback=None); + + self.send(""" + + + + + + + """) + + 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(""" + + + + + + + """) + + self.recv(""" + + + Invalid device Device22 + + + """) + + 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(""" + + + + + + + """) + + self.recv(""" + + + + """) + + 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(""" + + + + + + """) + + self.recv(""" + + + + """) + + self.recv(""" + + + + + + + + + + + """) + + self.recv(""" + + + + """) + + t1.join(); + time.sleep(.5) + + self.failUnlessEqual(results, ["accepted","fields","done"]); + # self.assertIn("nodeId", callback_data); + self.assertTrue(callback_data.has_key("nodeId")); + self.failUnlessEqual(callback_data["nodeId"], "Device33"); + # self.assertIn("timestamp", callback_data); + self.assertTrue(callback_data.has_key("timestamp")); + self.failUnlessEqual(callback_data["timestamp"], "2000-01-01T00:01:02"); + #self.assertIn("field_Voltage", callback_data); + self.assertTrue(callback_data.has_key("field_Voltage")); + 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(callback_data.has_key("field_TestBool")); + 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(""" + + + + """) + + self.send(""" + + + + + + + """) + + def testServiceDiscoveryComponent(self): + self.stream_start(mode='component', + plugins=['xep_0030', + 'xep_0323']); + + self.recv(""" + + + + """) + + self.send(""" + + + + + + + """) + + 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(""" + + + + + + """) + + self.recv(""" + + + + """) + + self.recv(""" + + + Timeout. + + + """) + + t1.join(); + time.sleep(.5) + + self.failUnlessEqual(results, ["accepted","failure"]); + # self.assertIn("nodeId", callback_data); + self.assertTrue(callback_data.has_key("nodeId")); + self.failUnlessEqual(callback_data["nodeId"], "Device33"); + # self.assertIn("timestamp", callback_data); + self.assertTrue(callback_data.has_key("timestamp")); + self.failUnlessEqual(callback_data["timestamp"], "2013-03-07T17:13:30"); + # self.assertIn("error_msg", callback_data); + self.assertTrue(callback_data.has_key("error_msg")); + 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(""" + + + + """) + + self.send(""" + + + + """) + + time.sleep(2) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + 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(""" + + + + """) + + # 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(""" + + + Invalid datetime in 'when' flag, cannot set a time in the past. Current time + + + """, 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(""" + + + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + """) + + 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(""" + + + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + """) + + 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(""" + + + + + + """) + + self.send(""" + + + + """) + + self.send(""" + + + + + + + + + + """) + + self.send(""" + + + + + """) + + 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(""" + + + + + + """) + + self.recv(""" + + + + """) + + self.recv(""" + + + + """) + + self.recv(""" + + + + + + + + + + + """) + + self.recv(""" + + + + """) + + t1.join(); + time.sleep(.5) + + self.failUnlessEqual(results, ["queued","started","fields","done"]); + # self.assertIn("nodeId", callback_data); + self.assertTrue(callback_data.has_key("nodeId")); + self.failUnlessEqual(callback_data["nodeId"], "Device33"); + # self.assertIn("timestamp", callback_data); + self.assertTrue(callback_data.has_key("timestamp")); + self.failUnlessEqual(callback_data["timestamp"], "2000-01-01T00:01:02"); + # self.assertIn("field_Voltage", callback_data); + self.assertTrue(callback_data.has_key("field_Voltage")); + 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(callback_data.has_key("field_TestBool")); + 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(""" + + + + + + """) + + self.recv(""" + + + + """) + + self.xmpp['xep_0323'].cancel_request(session=session); + + self.send(""" + + + + """) + + self.recv(""" + + + + """) + + 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(""" + + + + """) + + self.send(""" + + + + """) + + self.recv(""" + + + + """) + + self.send(""" + + + + """) + + # Test cancel of non-existing request + self.recv(""" + + + + """) + + self.send(""" + + + Cancel request received, no matching request is active. + + + """) + + time.sleep(2) + + # Ensure we don't get anything after cancellation + self.send(None) + + + +suite = unittest.TestLoader().loadTestsFromTestCase(TestStreamSensorData) + -- cgit v1.2.3