예제 #1
0
    def setUp(self):
        rospy_patcher = patch('hbp_nrp_cleserver.server.ROSNotificator.rospy')
        self.__mocked_rospy = rospy_patcher.start()

        self.__ros_notificator = ROSNotificator()

        # Be sure we create as many publishers as required.
        from hbp_nrp_cleserver.server import *
        number_of_publishers = 0
        for var_name in vars().keys():
            if (var_name.startswith("TOPIC_")):
                number_of_publishers += 1

        # Lifecycle topic not published by ROSNotificator
        number_of_publishers -= 1

        self.assertEqual(number_of_publishers,
                         self.__mocked_rospy.Publisher.call_count)

        # Assure that also the publish method of the rospy.Publisher is
        # injected as a mock here so that we can use it later in our single
        # test methods
        self.__mocked_pub = ROSNotificator.rospy.Publisher()
        self.__mocked_pub.publish = MagicMock()
        self.__mocked_rospy.Publisher.return_value = self.__mocked_pub
예제 #2
0
    def initialize(self, environment, except_hook):
        """
        Initializes the simulation
        :param environment: The environment that should be simulated
        :param except_hook: A method that should be called when there is a critical error
        """
        # Change working directory to experiment directory
        logger.info("Path is " + self.__exc.path)
        os.chdir(self.__exc.dir)

        # Create backend->frontend/client ROS notificator
        logger.info("Setting up backend Notificator")
        self.ros_notificator = ROSNotificator()
        Notificator.register_notification_function(
            lambda subtask, update_progress: self.ros_notificator.update_task(
                subtask, update_progress, True))

        # Number of subtasks is not used in frontend notificator logic
        self.ros_notificator.start_task("Neurorobotics Platform",
                                        "Neurorobotics Platform",
                                        number_of_subtasks=1,
                                        block_ui=True)
        self._notify("Starting Neurorobotics Platform")

        self._initialize(environment, except_hook)

        # Loading is completed.
        self._notify("Finished")
        self.ros_notificator.finish_task()

        logger.info("CLELauncher Finished.")
예제 #3
0
    def initialize(self, except_hook):
        """
        Initializes the simulation
        :param environment: The environment that should be simulated
        :param except_hook: A method that should be called when there is a critical error
        """
        # Change working directory to experiment directory
        logger.info("Path is " + self._sim_config.sim_dir)
        os.chdir(self._sim_config.sim_dir)

        # RNG seed for components, use config value if specified or generate a new one
        self.rng_seed = self.sim_config.rng_seed
        if self.rng_seed is None:
            logger.info(
                'No RNG seed specified in the exc, using random value.')
            self.rng_seed = random.randint(1, sys.maxint)
        logger.info('RNG seed = %i', self.rng_seed)

        # Create backend->frontend/client ROS notificator
        logger.info("Setting up backend Notificator")
        self.ros_notificator = ROSNotificator()
        Notificator.register_notification_function(
            lambda subtask, update_progress: self.ros_notificator.update_task(
                subtask, update_progress, True))

        # Number of subtasks is not used in frontend notificator logic
        self.ros_notificator.start_task("Neurorobotics Platform",
                                        "Neurorobotics Platform",
                                        number_of_subtasks=1,
                                        block_ui=True)
        self._notify("Starting Neurorobotics Platform")

        self._initialize(except_hook)

        # Loading is completed.
        self._notify("Finished")
        self.ros_notificator.finish_task()

        logger.info("CLELauncher Finished.")
예제 #4
0
    def test_shutdown(self):

        tmp = ROSNotificator()

        mock_unregister = Mock()
        tmp._ROSNotificator__ros_status_pub.unregister = mock_unregister
        tmp._ROSNotificator__ros_cle_error_pub.unregister = mock_unregister

        mock_publish = Mock()
        tmp._ROSNotificator__ros_status_pub.publish = mock_publish
        tmp._ROSNotificator__ros_cle_error_pub.publish = mock_publish

        # shutdown should unregister the publishers
        tmp.shutdown()

        self.assertEquals(mock_unregister.call_count, 2)
        self.assertEquals(tmp._ROSNotificator__ros_status_pub, None)
        self.assertEquals(tmp._ROSNotificator__ros_cle_error_pub, None)

        # publish methods should fail now
        tmp.publish_state('foo')
        tmp.publish_error('bar')
        self.assertEquals(mock_publish.call_count, 0)
예제 #5
0
class SimulationAssembly(object):
    """
    This class is the abstract base class of a simulation assembly
    """
    def __init__(self, sim_id, exc, bibi, par):
        """
        Creates a new simulation assembly

        :param sim_id: The simulation ID
        :param exc: The experiment configuration
        :param bibi: The BIBI configuration
        :param token: the request token in case we want to use the storage
        :param ctx_id: the ctx_id of collab based simulations
        """
        self.__sim_id = sim_id
        self.__exc = exc
        self.__bibi = bibi
        self.__token = par.get('token')
        self.__ctx_id = par.get('ctx_id')

        self._abort_initialization = None
        self.ros_notificator = None

    @property
    def bibi(self):
        """
        Gets the BIBI configuration for this simulation assembly
        """
        return self.__bibi

    @property
    def exc(self):
        """
        Gets the experiment configuration for this simulation assembly
        """
        return self.__exc

    @property
    def token(self):
        """
        Returns the token assigned to this simulation
        """
        return self.__token

    @property
    def ctx_id(self):
        """
        Returns the context id assigned to this simulation
        """
        return self.__ctx_id

    @property
    def sim_id(self):
        """
        Gets the simulation id
        """
        return self.__sim_id

    def initialize(self, environment, except_hook):
        """
        Initializes the simulation
        :param environment: The environment that should be simulated
        :param except_hook: A method that should be called when there is a critical error
        """
        # Change working directory to experiment directory
        logger.info("Path is " + self.__exc.path)
        os.chdir(self.__exc.dir)

        # Create backend->frontend/client ROS notificator
        logger.info("Setting up backend Notificator")
        self.ros_notificator = ROSNotificator()
        Notificator.register_notification_function(
            lambda subtask, update_progress: self.ros_notificator.update_task(
                subtask, update_progress, True))

        # Number of subtasks is not used in frontend notificator logic
        self.ros_notificator.start_task("Neurorobotics Platform",
                                        "Neurorobotics Platform",
                                        number_of_subtasks=1,
                                        block_ui=True)
        self._notify("Starting Neurorobotics Platform")

        self._initialize(environment, except_hook)

        # Loading is completed.
        self._notify("Finished")
        self.ros_notificator.finish_task()

        logger.info("CLELauncher Finished.")

    def _initialize(self, environment, except_hook):  # pragma: no cover
        """
        Internally initialize the simulation
        :param environment: The environment that should be simulated
        :param except_hook: A method that should be called when there is a critical error
        """
        raise NotImplementedError(
            "This method must be overridden in an implementation")

    def _notify(self, message):
        """
        Checks whether the simulation should abort immediately
        """
        if self._abort_initialization is not None:
            raise Exception("The simulation must abort due to: " +
                            self._abort_initialization)
        Notificator.notify(message, True)

    def run(self):  # pragma: no cover
        """
        Runs the simulation
        """
        raise NotImplementedError(
            "This method must be overridden in an implementation")

    def shutdown(self):  # pragma: no cover
        """
        Shuts down the simulation
        """
        raise NotImplementedError(
            "This method must be overridden in an implementation")
예제 #6
0
class SimulationAssembly(object):
    """
    This class is the abstract base class of a simulation assembly
    """
    def __init__(self, sim_config):
        """
        Creates a new simulation assembly

        :param sim_config: Simulation configuration
        """
        self._sim_config = sim_config

        self._abort_initialization = None
        self.ros_notificator = None
        self.rng_seed = None

    @property
    def sim_config(self):
        """
        Gets the sim_config
        """
        return self._sim_config

    @sim_config.setter
    def sim_config(self, sim_config):
        """
        Restrict external assignment of sim_config
        :raises AttributeError if the setter is called
        """
        # pylint: disable=no-self-use
        logger.info(
            "Raising exception instead of assigning {} to sim_config".format(
                sim_config))
        raise AttributeError(
            "sim_config has to be initialized on Assembly instantiation")

    # TODO: remove
    @property
    def simdir(self):
        """
        Gets the simulation directory
        """
        return self._sim_config.sim_dir

    @property
    def sim_dir(self):
        """
        Gets the simulation directory
        """
        return self._sim_config.sim_dir

    def initialize(self, except_hook):
        """
        Initializes the simulation
        :param environment: The environment that should be simulated
        :param except_hook: A method that should be called when there is a critical error
        """
        # Change working directory to experiment directory
        logger.info("Path is " + self._sim_config.sim_dir)
        os.chdir(self._sim_config.sim_dir)

        # RNG seed for components, use config value if specified or generate a new one
        self.rng_seed = self.sim_config.rng_seed
        if self.rng_seed is None:
            logger.info(
                'No RNG seed specified in the exc, using random value.')
            self.rng_seed = random.randint(1, sys.maxint)
        logger.info('RNG seed = %i', self.rng_seed)

        # Create backend->frontend/client ROS notificator
        logger.info("Setting up backend Notificator")
        self.ros_notificator = ROSNotificator()
        Notificator.register_notification_function(
            lambda subtask, update_progress: self.ros_notificator.update_task(
                subtask, update_progress, True))

        # Number of subtasks is not used in frontend notificator logic
        self.ros_notificator.start_task("Neurorobotics Platform",
                                        "Neurorobotics Platform",
                                        number_of_subtasks=1,
                                        block_ui=True)
        self._notify("Starting Neurorobotics Platform")

        self._initialize(except_hook)

        # Loading is completed.
        self._notify("Finished")
        self.ros_notificator.finish_task()

        logger.info("CLELauncher Finished.")

    def _initialize(self, except_hook):  # pragma: no cover
        """
        Internally initialize the simulation
        :param environment: The environment that should be simulated
        :param except_hook: A method that should be called when there is a critical error
        """
        raise NotImplementedError(
            "This method must be overridden in an implementation")

    def _notify(self, message):
        """
        Checks whether the simulation should abort immediately
        """
        if self._abort_initialization is not None:
            raise Exception("The simulation must abort due to: " +
                            self._abort_initialization)
        Notificator.notify(message, True)

    def run(self):  # pragma: no cover
        """
        Runs the simulation
        """
        raise NotImplementedError(
            "This method must be overridden in an implementation")

    def shutdown(self):  # pragma: no cover
        """
        Shuts down the simulation
        """
        raise NotImplementedError(
            "This method must be overridden in an implementation")
예제 #7
0
class TestROSNotificator(unittest.TestCase):
    def setUp(self):
        rospy_patcher = patch('hbp_nrp_cleserver.server.ROSNotificator.rospy')
        self.__mocked_rospy = rospy_patcher.start()

        self.__ros_notificator = ROSNotificator()

        # Be sure we create as many publishers as required.
        from hbp_nrp_cleserver.server import *
        number_of_publishers = 0
        for var_name in vars().keys():
            if (var_name.startswith("TOPIC_")):
                number_of_publishers += 1

        # Lifecycle topic not published by ROSNotificator
        number_of_publishers -= 1

        self.assertEqual(number_of_publishers,
                         self.__mocked_rospy.Publisher.call_count)

        # Assure that also the publish method of the rospy.Publisher is
        # injected as a mock here so that we can use it later in our single
        # test methods
        self.__mocked_pub = ROSNotificator.rospy.Publisher()
        self.__mocked_pub.publish = MagicMock()
        self.__mocked_rospy.Publisher.return_value = self.__mocked_pub

    def test_ros_node_initialized(self):
        self.__mocked_rospy.init_node.assert_called_with('ros_cle_simulation',
                                                         anonymous=True)

    def test_shutdown(self):

        tmp = ROSNotificator()

        mock_unregister = Mock()
        tmp._ROSNotificator__ros_status_pub.unregister = mock_unregister
        tmp._ROSNotificator__ros_cle_error_pub.unregister = mock_unregister

        mock_publish = Mock()
        tmp._ROSNotificator__ros_status_pub.publish = mock_publish
        tmp._ROSNotificator__ros_cle_error_pub.publish = mock_publish

        # shutdown should unregister the publishers
        tmp.shutdown()

        self.assertEquals(mock_unregister.call_count, 2)
        self.assertEquals(tmp._ROSNotificator__ros_status_pub, None)
        self.assertEquals(tmp._ROSNotificator__ros_cle_error_pub, None)

        # publish methods should fail now
        tmp.publish_state('foo')
        tmp.publish_error('bar')
        self.assertEquals(mock_publish.call_count, 0)

    def test_publish(self):

        self.__mocked_pub.reset_mock()
        self.__ros_notificator.publish_state('foo')
        self.__mocked_pub.publish.assert_called_once_with('foo')

        self.__mocked_pub.reset_mock()
        self.__ros_notificator.publish_error('bar')
        self.__mocked_pub.publish.assert_called_once_with('bar')

    def test_task(self):
        mock_publisher = Mock()
        self.__ros_notificator._ROSNotificator__ros_status_pub = mock_publisher
        self.__ros_notificator.start_task('task', 'subtask', 1, False)
        self.assertEquals(mock_publisher.publish.call_count, 1)
        self.__ros_notificator.update_task('new_subtask', True, False)
        self.assertEquals(mock_publisher.publish.call_count, 2)
        self.__ros_notificator.finish_task()
        self.assertEquals(mock_publisher.publish.call_count, 3)

    def test_start_task(self):
        self.__mocked_pub.reset_mock()

        task_name = 'test_name'
        subtask_name = 'test_subtaskname'
        number_of_subtasks = 1
        block_ui = False
        self.__ros_notificator.start_task(task_name, subtask_name,
                                          number_of_subtasks, block_ui)
        self.assertEqual(1, self.__mocked_pub.publish.call_count)
        message = {
            'progress': {
                'task': task_name,
                'subtask': subtask_name,
                'number_of_subtasks': number_of_subtasks,
                'subtask_index': 0,
                'block_ui': block_ui
            }
        }
        self.__mocked_pub.publish.assert_called_with(json.dumps(message))

        with patch.object(self.__ros_notificator,
                          'finish_task') as mock_finish:
            self.__ros_notificator.start_task(task_name, subtask_name,
                                              number_of_subtasks, block_ui)
            mock_finish.assert_called_once()

    @log_capture(level=logging.WARNING)
    def test_current_task_no_task(self, logcapture):
        self.__ros_notificator.update_task("new_subtask", True, True)
        logcapture.check(('hbp_nrp_cleserver.server.ROSNotificator', 'WARNING',
                          "Can't update a non existing task."))

    @log_capture(level=logging.WARNING)
    def test_finish_task_no_task(self, logcapture):
        self.__ros_notificator.finish_task()
        logcapture.check(('hbp_nrp_cleserver.server.ROSNotificator', 'WARNING',
                          "Can't finish a non existing task."))

    def test_task_notifier(self):

        with patch.object(self.__ros_notificator, 'start_task') as mock_start,\
             patch.object(self.__ros_notificator, 'finish_task') as mock_finish:

            with self.__ros_notificator.task_notifier('foo', 'bar') as tn:
                mock_start.assert_called_once_with('foo',
                                                   'bar',
                                                   number_of_subtasks=0,
                                                   block_ui=True)

            mock_finish.assert_called_once()