def testPushConnectionId(self):
        # Create and connect a second consumer port
        consumer_2 = MessageConsumerPort()
        self._portManager.addPort(consumer_2)
        objref = consumer_2._this()
        self._supplier.connectPort(objref, 'connection_2')

        # Set up 2 receivers to distinguish which connection received a message
        receiver_1 = MessageReceiver()
        self._consumer.registerMessage(None, None, receiver_1.messageReceived)

        receiver_2 = MessageReceiver()
        consumer_2.registerMessage(None, None, receiver_2.messageReceived)

        # Pack the messages ourselves and target the first connection
        messages_1 = []
        messages_1.append(CF.DataType('first', to_any(100)))
        messages_1.append(CF.DataType('second', to_any('some text')))
        messages_1.append(CF.DataType('third', to_any(0.25)))

        self._supplier.push(props_to_any(messages_1), 'connection_1')
        self.failUnless(receiver_1.waitMessages(3, 1.0))
        self.assertEqual(3, len(receiver_1.messages))
        self.failIf(receiver_2.waitMessages(1, 0.1))

        # Target the second connection with a different set of messages
        messages_2 = []
        messages_2.append(CF.DataType('one', to_any('abc')))
        messages_2.append(CF.DataType('two', to_any(False)))
        messages_2 = props_to_any(messages_2)
        self._supplier.push(messages_2, "connection_2")

        self.failUnless(receiver_2.waitMessages(2, 1.0))
        self.assertEqual(2, len(receiver_2.messages))
        self.failIf(receiver_1.waitMessages(4, 0.1))

        # Target both connections with yet another set of messages
        messages_3 = props_to_any([CF.DataType('all', to_any(3))])
        self._supplier.push(messages_3)
        self.failUnless(receiver_2.waitMessages(3, 1.0))
        self.assertEqual(3, len(receiver_2.messages))
        self.failUnless(receiver_1.waitMessages(4, 1.0))
        self.assertEqual(4, len(receiver_1.messages))

        # Target invalid connection
        messages_4 = props_to_any(
            [CF.DataType('bad', to_any('bad_connection'))])
        self.assertRaises(ValueError, self._supplier.push, messages_4,
                          'bad_connection')
        self.failIf(receiver_2.waitMessages(4, 0.1))
        self.failIf(receiver_1.waitMessages(5, 0.1))
        self.assertEqual(3, len(receiver_2.messages))
        self.assertEqual(4, len(receiver_1.messages))
    def testSendMessagesConnectionId(self):
        # Create and connect a second consumer port
        consumer_2 = MessageConsumerPort()
        self._portManager.addPort(consumer_2)
        objref = consumer_2._this()
        self._supplier.connectPort(objref, "connection_2")

        # Set up 2 receivers to distinguish which connection received a message
        receiver_1 = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver_1.messageReceived)

        receiver_2 = MessageReceiver()
        consumer_2.registerMessage("basic_message", BasicMessage,
                                   receiver_2.messageReceived)

        # Target first connection
        messages_1 = [BasicMessage(value=x) for x in xrange(2)]
        self.assertEqual(0, len(receiver_1.messages))
        self.assertEqual(0, len(receiver_2.messages))
        self._supplier.sendMessages(messages_1, "connection_1")

        # Wait for the first receiver to get all messages; the second receiver
        # ought to get none (give it some time due to threading)
        self.failUnless(receiver_1.waitMessages(2, 1.0))
        self.assertEqual(2, len(receiver_1.messages))
        self.failIf(receiver_2.waitMessages(1, 0.1))

        # Target the second connection this time with a different set of
        # messages
        messages_2 = [BasicMessage(value=x) for x in xrange(2, 5)]
        self._supplier.sendMessages(messages_2, "connection_2")

        # Wait for the second receiver to get all the messages (and check at
        # least the first value)
        self.failUnless(receiver_2.waitMessages(len(messages_2), 1.0))
        self.assertEqual(3, len(receiver_2.messages))
        self.assertEqual(2, receiver_2.messages[0].value)
        self.failIf(receiver_1.waitMessages(3, 0.1))

        # Target both connections
        self._supplier.sendMessages(messages_1)
        self.failUnless(receiver_1.waitMessages(4, 1.0))
        self.assertEqual(4, len(receiver_1.messages))
        self.failUnless(receiver_2.waitMessages(5, 1.0))
        self.assertEqual(5, len(receiver_2.messages))

        # Target invalid connection
        messages_3 = [BasicMessage(value=5)]
        self.assertRaises(ValueError, self._supplier.sendMessages, messages_3,
                          "bad_connection")
        self.failIf(receiver_1.waitMessages(5, 0.1))
        self.failIf(receiver_2.waitMessages(6, 0.1))
    def testSendMessageConnectionId(self):
        # Create and connect a second consumer port
        consumer_2 = MessageConsumerPort()
        self._portManager.addPort(consumer_2)
        objref = consumer_2._this()
        self._supplier.connectPort(objref, "connection_2")

        # Set up 2 receivers to distinguish which connection received a message
        receiver_1 = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver_1.messageReceived)

        receiver_2 = MessageReceiver()
        consumer_2.registerMessage("basic_message", BasicMessage,
                                   receiver_2.messageReceived)

        # Target the first connection
        msg = BasicMessage()
        msg.value = 1
        self.assertEqual(0, len(receiver_1.messages))
        self.assertEqual(0, len(receiver_2.messages))
        self._supplier.sendMessage(msg, connectionId="connection_1")

        self.failUnless(receiver_1.waitMessages(1, 1.0))
        self.assertEqual("basic_message", receiver_1.messages[0].getId())
        self.assertEqual(1, receiver_1.messages[0].value)

        # Second should not receive it (give it a little time just in case)
        self.failIf(receiver_2.waitMessages(1, 0.1))

        # Target the second connection this time
        msg.value = 2
        self._supplier.sendMessage(msg, connectionId="connection_2")

        self.failUnless(receiver_2.waitMessages(1, 1.0))
        self.assertEqual("basic_message", receiver_2.messages[0].getId())
        self.assertEqual(2, receiver_2.messages[0].value)

        # This time, the first should not receive it
        self.failIf(receiver_1.waitMessages(2, 0.1))

        # Target both connections
        msg.value = 3
        self._supplier.sendMessage(msg)

        self.failUnless(receiver_1.waitMessages(2, 1.0))
        self.failUnless(receiver_2.waitMessages(2, 1.0))

        # Target invalid connection
        msg.value = 4
        self.assertRaises(ValueError, self._supplier.sendMessage, msg,
                          "bad_connection")
    def setUp(self):
        self._portManager = PortManager()
        self._supplier = MessageSupplierPort()
        self._consumer = MessageConsumerPort()

        self._portManager.addPort(self._supplier)
        self._portManager.addPort(self._consumer)

        # Connect the supplier and consumer
        objref = self._consumer._this()
        self._supplier.connectPort(objref, "connection_1")

        # Simulate component start
        self._portManager.start()
    def __init__(self, identifier, execparams):
        loggerName = (execparams['NAME_BINDING'].replace('/',
                                                         '.')).rsplit("_",
                                                                      1)[0]
        Component.__init__(self, identifier, execparams, loggerName=loggerName)
        ThreadedComponent.__init__(self)

        # self.auto_start is deprecated and is only kept for API compatibility
        # with 1.7.X and 1.8.0 components.  This variable may be removed
        # in future releases
        self.auto_start = False
        # Instantiate the default implementations for all ports on this component
        self.port_dataFloat_in = MessageConsumerPort(thread_sleep=0.1,
                                                     parent=self)
        self.port_dataFloat_in2 = MessageConsumerPort(thread_sleep=0.1,
                                                      parent=self)
class MessagingTest(unittest.TestCase):
    def setUp(self):
        self._portManager = PortManager()
        self._supplier = MessageSupplierPort()
        self._consumer = MessageConsumerPort()

        self._portManager.addPort(self._supplier)
        self._portManager.addPort(self._consumer)

        # Connect the supplier and consumer
        objref = self._consumer._this()
        self._supplier.connectPort(objref, "connection_1")

        # Simulate component start
        self._portManager.start()

    def tearDown(self):
        self._portManager.stop()
        self._portManager.releaseObject()

    def testSendMessage(self):
        receiver = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver.messageReceived)

        msg = BasicMessage()
        msg.value = 1

        self._supplier.sendMessage(msg)

        # Unlike C++, the Python message consumer is threaded, so we need to
        # give it some time to receive the message
        self.failUnless(receiver.waitMessages(1, 1.0))

        self.assertEqual("basic_message", receiver.messages[0].getId())
        self.assertEqual(msg.value, receiver.messages[0].value)

    def testGenericAndSpecificMessageCallback(self):
        receiver = MessageReceiver()
        generic_receiver = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver.messageReceived)
        self._consumer.registerMessage(None, BasicMessage,
                                       generic_receiver.messageReceived)

        msg = BasicMessage()
        msg.value = 1

        self._supplier.sendMessage(msg)

        # Unlike C++, the Python message consumer is threaded, so we need to
        # give it some time to receive the message
        self.failUnless(receiver.waitMessages(1, 1.0))
        self.failUnless(generic_receiver.waitMessages(1, 1.0))

        self.assertEqual("basic_message", receiver.messages[0].getId())
        self.assertEqual(msg.value, receiver.messages[0].value)

        self.assertEqual("basic_message", generic_receiver.messages[0].id)
        self.assertEqual(1, len(generic_receiver.messages[0].value._v))
        self.assertEqual("basic_message::value",
                         generic_receiver.messages[0].value._v[0].id)
        self.assertEqual(1, generic_receiver.messages[0].value._v[0].value._v)

    def testSendMessageConnectionId(self):
        # Create and connect a second consumer port
        consumer_2 = MessageConsumerPort()
        self._portManager.addPort(consumer_2)
        objref = consumer_2._this()
        self._supplier.connectPort(objref, "connection_2")

        # Set up 2 receivers to distinguish which connection received a message
        receiver_1 = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver_1.messageReceived)

        receiver_2 = MessageReceiver()
        consumer_2.registerMessage("basic_message", BasicMessage,
                                   receiver_2.messageReceived)

        # Target the first connection
        msg = BasicMessage()
        msg.value = 1
        self.assertEqual(0, len(receiver_1.messages))
        self.assertEqual(0, len(receiver_2.messages))
        self._supplier.sendMessage(msg, connectionId="connection_1")

        self.failUnless(receiver_1.waitMessages(1, 1.0))
        self.assertEqual("basic_message", receiver_1.messages[0].getId())
        self.assertEqual(1, receiver_1.messages[0].value)

        # Second should not receive it (give it a little time just in case)
        self.failIf(receiver_2.waitMessages(1, 0.1))

        # Target the second connection this time
        msg.value = 2
        self._supplier.sendMessage(msg, connectionId="connection_2")

        self.failUnless(receiver_2.waitMessages(1, 1.0))
        self.assertEqual("basic_message", receiver_2.messages[0].getId())
        self.assertEqual(2, receiver_2.messages[0].value)

        # This time, the first should not receive it
        self.failIf(receiver_1.waitMessages(2, 0.1))

        # Target both connections
        msg.value = 3
        self._supplier.sendMessage(msg)

        self.failUnless(receiver_1.waitMessages(2, 1.0))
        self.failUnless(receiver_2.waitMessages(2, 1.0))

        # Target invalid connection
        msg.value = 4
        self.assertRaises(ValueError, self._supplier.sendMessage, msg,
                          "bad_connection")

    def testSendMessages(self):
        receiver = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver.messageReceived)
        self._consumer.registerMessage("test_message", TestMessage,
                                       receiver.messageReceived)

        # Send two different message types in one batch
        messages = [
            BasicMessage(value=1),
            TestMessage(item_float=2.0, item_string="two"),
            BasicMessage(value=3)
        ]

        self.assertEqual(0, len(receiver.messages))
        self._supplier.sendMessages(messages)
        self.failUnless(receiver.waitMessages(len(messages), 1.0))
        self.assertEqual('basic_message', receiver.messages[0].getId())
        self.assertEqual(1, receiver.messages[0].value)
        self.assertEqual('test_message', receiver.messages[1].getId())
        self.assertEqual(2.0, receiver.messages[1].item_float)
        self.assertEqual("two", receiver.messages[1].item_string)
        self.assertEqual('basic_message', receiver.messages[2].getId())
        self.assertEqual(3, receiver.messages[2].value)

    def testSendMessagesConnectionId(self):
        # Create and connect a second consumer port
        consumer_2 = MessageConsumerPort()
        self._portManager.addPort(consumer_2)
        objref = consumer_2._this()
        self._supplier.connectPort(objref, "connection_2")

        # Set up 2 receivers to distinguish which connection received a message
        receiver_1 = MessageReceiver()
        self._consumer.registerMessage("basic_message", BasicMessage,
                                       receiver_1.messageReceived)

        receiver_2 = MessageReceiver()
        consumer_2.registerMessage("basic_message", BasicMessage,
                                   receiver_2.messageReceived)

        # Target first connection
        messages_1 = [BasicMessage(value=x) for x in xrange(2)]
        self.assertEqual(0, len(receiver_1.messages))
        self.assertEqual(0, len(receiver_2.messages))
        self._supplier.sendMessages(messages_1, "connection_1")

        # Wait for the first receiver to get all messages; the second receiver
        # ought to get none (give it some time due to threading)
        self.failUnless(receiver_1.waitMessages(2, 1.0))
        self.assertEqual(2, len(receiver_1.messages))
        self.failIf(receiver_2.waitMessages(1, 0.1))

        # Target the second connection this time with a different set of
        # messages
        messages_2 = [BasicMessage(value=x) for x in xrange(2, 5)]
        self._supplier.sendMessages(messages_2, "connection_2")

        # Wait for the second receiver to get all the messages (and check at
        # least the first value)
        self.failUnless(receiver_2.waitMessages(len(messages_2), 1.0))
        self.assertEqual(3, len(receiver_2.messages))
        self.assertEqual(2, receiver_2.messages[0].value)
        self.failIf(receiver_1.waitMessages(3, 0.1))

        # Target both connections
        self._supplier.sendMessages(messages_1)
        self.failUnless(receiver_1.waitMessages(4, 1.0))
        self.assertEqual(4, len(receiver_1.messages))
        self.failUnless(receiver_2.waitMessages(5, 1.0))
        self.assertEqual(5, len(receiver_2.messages))

        # Target invalid connection
        messages_3 = [BasicMessage(value=5)]
        self.assertRaises(ValueError, self._supplier.sendMessages, messages_3,
                          "bad_connection")
        self.failIf(receiver_1.waitMessages(5, 0.1))
        self.failIf(receiver_2.waitMessages(6, 0.1))

    def testPush(self):
        receiver = MessageReceiver()
        self._consumer.registerMessage(None, None, receiver.messageReceived)

        # Pack the messages ourselves
        messages = []
        messages.append(CF.DataType('first', to_any(100)))
        messages.append(CF.DataType('second', to_any('some text')))
        messages.append(CF.DataType('third', to_any(0.25)))

        self._supplier.push(props_to_any(messages))

        self.failUnless(receiver.waitMessages(3, 1.0))
        self.assertEqual(3, len(receiver.messages))
        self.assertEqual(100, from_any(receiver.messages[0].value))
        self.assertEqual('some text', from_any(receiver.messages[1].value))
        self.assertEqual(0.25, from_any(receiver.messages[2].value))

    def testPushConnectionId(self):
        # Create and connect a second consumer port
        consumer_2 = MessageConsumerPort()
        self._portManager.addPort(consumer_2)
        objref = consumer_2._this()
        self._supplier.connectPort(objref, 'connection_2')

        # Set up 2 receivers to distinguish which connection received a message
        receiver_1 = MessageReceiver()
        self._consumer.registerMessage(None, None, receiver_1.messageReceived)

        receiver_2 = MessageReceiver()
        consumer_2.registerMessage(None, None, receiver_2.messageReceived)

        # Pack the messages ourselves and target the first connection
        messages_1 = []
        messages_1.append(CF.DataType('first', to_any(100)))
        messages_1.append(CF.DataType('second', to_any('some text')))
        messages_1.append(CF.DataType('third', to_any(0.25)))

        self._supplier.push(props_to_any(messages_1), 'connection_1')
        self.failUnless(receiver_1.waitMessages(3, 1.0))
        self.assertEqual(3, len(receiver_1.messages))
        self.failIf(receiver_2.waitMessages(1, 0.1))

        # Target the second connection with a different set of messages
        messages_2 = []
        messages_2.append(CF.DataType('one', to_any('abc')))
        messages_2.append(CF.DataType('two', to_any(False)))
        messages_2 = props_to_any(messages_2)
        self._supplier.push(messages_2, "connection_2")

        self.failUnless(receiver_2.waitMessages(2, 1.0))
        self.assertEqual(2, len(receiver_2.messages))
        self.failIf(receiver_1.waitMessages(4, 0.1))

        # Target both connections with yet another set of messages
        messages_3 = props_to_any([CF.DataType('all', to_any(3))])
        self._supplier.push(messages_3)
        self.failUnless(receiver_2.waitMessages(3, 1.0))
        self.assertEqual(3, len(receiver_2.messages))
        self.failUnless(receiver_1.waitMessages(4, 1.0))
        self.assertEqual(4, len(receiver_1.messages))

        # Target invalid connection
        messages_4 = props_to_any(
            [CF.DataType('bad', to_any('bad_connection'))])
        self.assertRaises(ValueError, self._supplier.push, messages_4,
                          'bad_connection')
        self.failIf(receiver_2.waitMessages(4, 0.1))
        self.failIf(receiver_1.waitMessages(5, 0.1))
        self.assertEqual(3, len(receiver_2.messages))
        self.assertEqual(4, len(receiver_1.messages))