except ImportError: import Queue as queue # Local utilities from tests.mqtt_utilities import find_mqtt_server from tests.utilities import WrappedProcess # ------------------------------------------------------------------------------ # Documentation strings format __docformat__ = "restructuredtext en" APP_ID = str(uuid.uuid4()) SVC_SPEC = "pelix.test.remote" MQTT_SERVER = find_mqtt_server() if not MQTT_SERVER: raise unittest.SkipTest("No valid MQTT server found") # ------------------------------------------------------------------------------ class RemoteService(object): """ Exported service """ def __init__(self, state_queue, event): """ Sets up members ;param state_queue: Queue to store status
class MqttServiceTest(unittest.TestCase): """ Tests the MQTT utility service """ HOST = find_mqtt_server() PORT = 1883 def setUp(self): """ Prepares a framework and a registers a service to export """ # Prepare a temporary configuration folder self.conf_dir = tempfile.mkdtemp() # Create the framework # The MQTT component is automatically started self.framework = pelix.framework.create_framework( ('pelix.ipopo.core', 'pelix.services.configadmin', 'pelix.services.mqtt'), {'configuration.folder': self.conf_dir}) self.framework.start() # Get the configuration admin service context = self.framework.get_bundle_context() self.config_ref = context.get_service_reference( services.SERVICE_CONFIGURATION_ADMIN) self.config = context.get_service(self.config_ref) def tearDown(self): """ Cleans up for next test """ # Stop the framework pelix.framework.FrameworkFactory.delete_framework(self.framework) self.framework = None # Clean up shutil.rmtree(self.conf_dir) def test_no_config(self): """ Tests MQTT utility without configuration """ # Wait a bit time.sleep(.5) # Check if a service is active context = self.framework.get_bundle_context() svc_ref = context.get_service_reference( services.SERVICE_MQTT_CONNECTION) self.assertIsNone(svc_ref, "Found a MQTT connection") def _setup_mqtt(self, context): """ Common code for MQTT service creation """ # Setup MQTT connection config = self.config.create_factory_configuration( services.MQTT_CONNECTOR_FACTORY_PID) config.update({"host": self.HOST, "port": self.PORT}) # Wait for service for _ in range(10): svc_ref = context.get_service_reference( services.SERVICE_MQTT_CONNECTION, "(id={})".format(config.get_pid())) if svc_ref is not None: break time.sleep(.5) else: self.fail("Connection Service not found") return config, svc_ref def test_configuration(self): """ Tests service configuration """ # Prepare service context = self.framework.get_bundle_context() config, svc_ref = self._setup_mqtt(context) # Assert we have the same PID props = svc_ref.get_properties() self.assertEqual(props['host'], self.HOST) self.assertEqual(props['port'], self.PORT) self.assertEqual(props['id'], config.get_pid()) # Delete configuration config.delete() # Wait for service to be unregistered context = self.framework.get_bundle_context() for _ in range(10): svc_ref = context.get_service_reference( services.SERVICE_MQTT_CONNECTION, "(id={})".format(config.get_pid())) if svc_ref is None: break time.sleep(.5) else: self.fail("Connection Service still there") def __send_message(self, client, topic, qos): """ Sends a message using the given client (content is generated) :param client: MQTT client :param topic: Message topic :param qos: Requested quality of service :return: Payload of the message """ payload = list(string.ascii_letters) random.shuffle(payload) payload = ''.join(payload).encode("utf-8") client.publish(topic, payload, qos=qos) return payload def test_messages(self): """ Tests messages publication and reception """ # Prepare service 1 context = self.framework.get_bundle_context() config, svc_ref = self._setup_mqtt(context) mqtt_1 = context.get_service(svc_ref) # Prepare service 2 config_2, svc_ref = self._setup_mqtt(context) mqtt_2 = context.get_service(svc_ref) # Assert that we have two different services self.assertIsNot(mqtt_1, mqtt_2, "Same services returned") # Register a publisher listener = Listener() lst_reg = context.register_service( services.SERVICE_MQTT_LISTENER, listener, {services.PROP_MQTT_TOPICS: "/pelix/test/#"}) # Check the initial test condition self.assertListEqual(listener.messages, [], "Invalid precondition") # Send a message topic = "/pelix/test/foobar" payload = self.__send_message(mqtt_1, topic, 1) # Wait for it for _ in range(10): try: msg_topic, msg_payload, qos = listener.messages.pop() break except IndexError: time.sleep(.5) else: self.fail("Got no message") # Check message self.assertEqual(msg_topic, topic) self.assertEqual(msg_payload, payload) # Test with a filtered out topic topic = "/pelix/foo/bar" self.__send_message(mqtt_1, topic, 1) # Wait for something for _ in range(6): try: msg_topic, msg_payload, qos = listener.messages.pop() except IndexError: time.sleep(.5) else: # It is possible we got a copy of the previous message # (QOS 1: at least one time) if msg_topic == topic: self.fail( "Got a message that should be filtered: {}".format( msg_topic)) # Change topic filter lst_reg.set_properties({services.PROP_MQTT_TOPICS: "/pelix/foo/#"}) payload = self.__send_message(mqtt_1, topic, 1) # Wait for it for _ in range(10): try: msg_topic, msg_payload, qos = listener.messages.pop() break except IndexError: time.sleep(.5) else: self.fail("Got no message") # Check message self.assertEqual(msg_topic, topic) self.assertEqual(msg_payload, payload) # Unregister service lst_reg.unregister() # Clean up del listener.messages[:] # Send a message self.__send_message(mqtt_1, topic, 1) # Wait for something for _ in range(6): try: listener.messages.pop() except IndexError: time.sleep(.5) else: self.fail("Got an unexpected message") # Clean up config.delete() config_2.delete()