diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICBrainLoader.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICBrainLoader.py
index 7829aafc9bf5152d919deddd4f13391dd4d805b1..fd43c6d2d21c8b11bc76ac30f572ae1dbc1a60a6 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICBrainLoader.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICBrainLoader.py
@@ -24,7 +24,7 @@
"""`
Load a brain network's MUSIC proxies
"""
-from hbp_nrp_cle.brainsim.pynn import simulator as sim
+import pyNN.nest as sim
import hbp_nrp_cle.tf_framework.config as tf_config
from hbp_nrp_music_xml.pynn.factory import PyNNProxyFactory
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py
index c463006bb24e581b3d907598fc21c12a6792f23a..3b5b6180a372aef90ed99844761765040408519d 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/cle/MUSICPyNNCommunicationAdapter.py
@@ -27,7 +27,7 @@ instead of direct population access. Maxmimum code reuse and minimal duplication
where possible.
"""
from hbp_nrp_cle.brainsim.pynn_nest.PyNNNestCommunicationAdapter import PyNNNestCommunicationAdapter
-from hbp_nrp_cle.brainsim.pynn import simulator as sim
+import pyNN.nest as sim
import hbp_nrp_cle.tf_framework.config as tf_config
from hbp_nrp_music_interface.bibi.bibi_music_config import MUSICConfiguration
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICBrainProcess.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICBrainProcess.py
index 84948aa284b3134661c75362556a2060f82c3d77..35560fd2fb4cb19f3ef0a6be065777ef8b948f3c 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICBrainProcess.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICBrainProcess.py
@@ -25,7 +25,7 @@
A distributed brain process that can be launched standalone on remote hosts.
"""
from hbp_nrp_cle.brainsim import config
-from hbp_nrp_cle.brainsim.pynn import simulator as sim
+import pyNN.nest as sim
from hbp_nrp_cle.brainsim.pynn.PyNNControlAdapter import PyNNControlAdapter
from hbp_nrp_cle.cle.ClosedLoopEngine import ClosedLoopEngine
import hbp_nrp_cle.tf_framework.config as tf_config
@@ -80,7 +80,7 @@ class MUSICBrainProcess(object):
config.rng_seed = int(rng_seed)
# spawn CLE components that will handle loading the brain file and interfaces
- self._brain_controller = PyNNControlAdapter()
+ self._brain_controller = PyNNControlAdapter(sim)
self._brain_controller.initialize()
self._brain_controller.load_brain(brain_file, **pop_dict)
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICCLEProcess.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICCLEProcess.py
new file mode 100644
index 0000000000000000000000000000000000000000..1706d2c128498acf3bdd9bc9c0ac6fbf1e2740c4
--- /dev/null
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICCLEProcess.py
@@ -0,0 +1,190 @@
+# ---LICENSE-BEGIN - DO NOT CHANGE OR MOVE THIS HEADER
+# This file is part of the Neurorobotics Platform software
+# Copyright (C) 2014,2015,2016,2017 Human Brain Project
+# https://www.humanbrainproject.eu
+#
+# The Human Brain Project is a European Commission funded project
+# in the frame of the Horizon2020 FET Flagship plan.
+# http://ec.europa.eu/programmes/horizon2020/en/h2020-section/fet-flagships
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+# ---LICENSE-END
+"""
+This module contains the CLE process logic for the simulation assembly using MUSIC
+"""
+
+import os
+import argparse
+import logging
+from hbp_nrp_cleserver.server.CLEGazeboSimulationAssembly import CLEGazeboSimulationAssembly
+from hbp_nrp_music_interface.cle.MUSICPyNNCommunicationAdapter import MUSICPyNNCommunicationAdapter
+from hbp_nrp_music_interface.cle.MUSICPyNNControlAdapter import MUSICPyNNControlAdapter
+
+import pyNN.nest as nestsim
+import music
+
+logger = logging.getLogger(__name__)
+
+
+class MusicCLESimulationAssembly(CLEGazeboSimulationAssembly):
+ """
+ Defines the assembly of a simulation using MUSIC
+ """
+
+ def __init__(self, sim_id, exc, bibi_model, **par):
+ """
+ Creates a new simulation assembly to simulate an experiment using the CLE and Gazebo
+ :param sim_id: The simulation id
+ :param exc: The experiment configuration
+ :param bibi_model: The BIBI configuration
+ """
+ super(MusicCLESimulationAssembly, self).__init__(sim_id, exc, bibi_model, **par)
+
+ def _create_brain_adapters(self):
+ """
+ Creates the adapter components for the neural simulator
+
+ :return: A tuple of the communication and control adapter for the neural simulator
+ """
+ logger.info('Using MUSIC configuration and adapters for CLE')
+
+ # write pid to lock file so launcher can always terminate us
+ # (failsafe)
+ pid = os.getpid()
+ with open('{}.lock'.format(pid), 'w') as pf:
+ pf.write('{}'.format(pid))
+
+ # initialize music and set the CLE to use MUSIC adapters
+ music.Setup()
+
+ braincomm = MUSICPyNNCommunicationAdapter()
+ braincontrol = MUSICPyNNControlAdapter(nestsim)
+ return braincomm, braincontrol
+
+if __name__ == '__main__': # pragma: no cover
+ # TODO: This should be separated into its own method such that we can unit
+ # test this code
+ simulation = None
+
+ # exit code, 0 for success and -1 for any failures
+ mpi_returncode = 0
+ try:
+ if os.environ["ROS_MASTER_URI"] == "":
+ raise Exception("You should run ROS first.")
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--exdconf', dest='exd_file',
+ help='specify the ExDConfiguration file', required=True)
+ parser.add_argument('--environment', dest='environment_file',
+ help='specify the environment file', required=True)
+ parser.add_argument('--experiment-path', dest='path',
+ help='specify the base experiment path', required=True)
+ parser.add_argument('--gzserver-host', dest='gzserver_host',
+ help='the gzserver target host', required=True)
+ parser.add_argument('--reservation', dest='reservation', default=None,
+ help='cluster resource reservation', required=False)
+ parser.add_argument('--sim-id', dest='sim_id', type=int,
+ help='the simulation id to use', required=True)
+ parser.add_argument('--timeout', dest='timeout',
+ help='the simulation default time allocated', required=True)
+ parser.add_argument('--rng-seed', dest='rng_seed',
+ help='the global experiment RNG seed', required=True)
+ parser.add_argument('-v', '--verbose', action='store_true',
+ help='increase output verbosity')
+
+ args = parser.parse_args()
+
+ # expand any parameters (e.g. NRP_EXPERIMENTS_DIRECTORY) in paths
+ args.exd_file = os.path.expandvars(args.exd_file)
+ args.environment_file = os.path.expandvars(args.environment_file)
+ args.path = os.path.expandvars(args.path)
+
+ # simplified launch process below from ROSCLESimulationFactory.py, avoid circular depdency
+ # by importing here
+ import rospy
+ from hbp_nrp_cleserver.server import ROS_CLE_NODE_NAME
+ from hbp_nrp_cleserver.server.ROSCLESimulationFactory import set_up_logger
+ from hbp_nrp_cleserver.server.ROSCLESimulationFactory import get_experiment_data
+
+ # reconfigure the logger to stdout as done in ROSCLESimulationFactory.py otherwise all
+ # output will be trapped by the ROS logger after the first ROS node is
+ # initialized
+ rospy.init_node(ROS_CLE_NODE_NAME, anonymous=True)
+ set_up_logger(None, args.verbose)
+
+ exd, bibi = get_experiment_data(args.exd_file)
+
+ # parse the timeout string command line argument into a valid datetime
+ import dateutil.parser as datetime_parser
+ timeout_parsed = datetime_parser.parse(args.timeout.replace('_', ' '))
+
+ # check the reservation argument, if empty default to None
+ if args.reservation == '':
+ args.reservation = None
+
+ # override the experiment RNG seed with the command line value
+ exd.rngSeed = int(args.rng_seed)
+
+ simulation = MusicCLESimulationAssembly(args.sim_id,
+ exd,
+ bibi,
+ gzserver_host=args.gzserver_host,
+ reservation=args.reservation,
+ timeout=timeout_parsed)
+ simulation.initialize(args.environment_file, None)
+ if simulation.cle_server is None:
+ raise Exception(
+ "Error in cle_function_init. Cannot start simulation.")
+
+ # FIXME: This should be done more cleanly within the adapter, see [NRRPLT-4858]
+ # the tag is a magic number to avoid circular build/release dependency for now but
+ # this will be removed when the referenced bug is fixed
+ # notify MPI/music processes that configuration is complete
+ from mpi4py import MPI
+ for rank in xrange(MPI.COMM_WORLD.Get_size()):
+ if rank != MPI.COMM_WORLD.Get_rank():
+ MPI.COMM_WORLD.send('ready', dest=rank, tag=100)
+ MPI.COMM_WORLD.Barrier()
+
+ logger.info('Starting CLE.')
+ simulation.run() # This is a blocking call, not to be confused with
+ # threading.Thread.start
+
+ except Exception as e: # pylint: disable=broad-except
+
+ # if running through MPI, catch Exception and terminate below to ensure brain processes
+ # are also killed
+ logger.error(
+ 'CLE aborted with message {}, terminating.'.format(e.message))
+ # if no logger
+ print 'CLE aborted with message {}, terminating.'.format(e.message)
+ logger.exception(e)
+ mpi_returncode = -1
+
+ finally:
+
+ # always attempt to shutdown the CLE launcher and release resources
+ if simulation:
+ logger.info('Shutting down CLE.')
+ simulation.shutdown()
+ logger.info('Shutdown complete, terminating.')
+
+ # terminate the MUSIC spawned brain processes
+ # send a shutdown message in case the brain processes are in a recv loop at startup since they
+ # seem to block and ignore the Abort command until receiving a message
+ from mpi4py import MPI
+ for rank in xrange(MPI.COMM_WORLD.Get_size()):
+ MPI.COMM_WORLD.isend('shutdown', dest=rank, tag=100)
+ MPI.COMM_WORLD.Abort(mpi_returncode)
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICLauncher.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICLauncher.py
index 2558bf09b1be521492a090e584175b769eac4327..f6e2e6c53e76a85942ab2fea77cc2acec6ad4e67 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICLauncher.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/MUSICLauncher.py
@@ -35,23 +35,21 @@ import random
import sys
+# This class intentionally does not inherit SimulationServer (even though it is an implementation of
+# it) in order to avoid duplicate notificators
class MUSICLauncher(object):
"""
Setup, build, and launch a distributed MUSIC instance that will spawn the CLE and
requested brain processes.
"""
- # pylint: disable=too-many-arguments
- def __init__(self, exd_file, bibi_file, env_file, exp_path, server_host, reservation,
- sim_id, timeout):
+ def __init__(self, sim_id, exc, bibi, **par):
"""
Store all experiment configuration parameters so that they can be propagated
to the remote hosts.
- :param exd_file Absolute path to the ExDConf file.
- :param bibi_file Absolute path to the BIBI file.
- :param env_file Absolute path to the simulation environment file.
- :param exp_path Absolute path to the base dir of the experiment files.
+ :param exc: the experiment configuration
+ :param bibi: the BIBI configuration.
:param server_host Target Gazebo/brain process host (e.g. local or lugano)
:param reservation Reservation string for cluster backend (None is a valid option)
:param sim_id The id of the simulation/experiment to be launched.
@@ -60,40 +58,44 @@ class MUSICLauncher(object):
# we need to replace absolute paths with relative environment variable-based paths for the
# remote hosts that may not share the same file structure
- nrp_models_path = os.environ.get('NRP_MODELS_DIRECTORY').rstrip('/')
nrp_experiments_path = os.environ.get('NRP_EXPERIMENTS_DIRECTORY').rstrip('/')
- self._exd_file = exd_file.replace(nrp_experiments_path, '$NRP_EXPERIMENTS_DIRECTORY')
- self._bibi_file = bibi_file.replace(nrp_experiments_path, '$NRP_EXPERIMENTS_DIRECTORY')
- self._env_file = env_file.replace(nrp_models_path, '$NRP_MODELS_DIRECTORY')
- self._exp_path = exp_path.replace(nrp_experiments_path, '$NRP_EXPERIMENTS_DIRECTORY')
+ self._exd_file = exc.path.replace(nrp_experiments_path, '$NRP_EXPERIMENTS_DIRECTORY')
+ self._bibi_file = bibi.path.replace(nrp_experiments_path, '$NRP_EXPERIMENTS_DIRECTORY')
+ self._exp_path = exc.dir.replace(nrp_experiments_path, '$NRP_EXPERIMENTS_DIRECTORY')
# store the other launch parameters as provided
- self._server_host = server_host
- self._reservation = reservation
+ self._server_host = par['gzserver_host']
+ self._reservation = par['reservation']
self._sim_id = sim_id
- self._timeout = timeout
+ self._timeout = par['timeout']
+
+ self.__exc = exc
+ self.__bibi = bibi
+ self._env_file = None
# host specific launch configuration/allocation
self._launcher = None
-
# the MPI process launcher for the CLE and brain processes
- self.cle_server = None
+ self.mpilauncher = None
- def init(self, bibi, exd):
+ # we should call the except_hook when something goes wrong in the simulation, but currently
+ # we don't
+ # pylint: disable=unused-argument
+ def initialize(self, environment_file, except_hook):
"""
Construct the MUSIC launch configuration that will spawn CLE + brain processes
on distributed hosts.
-
- :param bibi The BIBI configuration to launch brain processes with.
- :param exd The parsed ExDConf configuration to launch brain processes with.
"""
+ nrp_models_path = os.environ.get('NRP_MODELS_DIRECTORY').rstrip('/')
+ self._env_file = environment_file.replace(nrp_models_path, '$NRP_MODELS_DIRECTORY')
+
# create a host specific launcher
if self._server_host == 'local':
self._launcher = LocalLauncher()
elif self._server_host == 'lugano':
- self._launcher = LuganoLauncher(exd.bibiConf.processes + 1,
+ self._launcher = LuganoLauncher(self.__exc.bibiConf.processes + 1,
self._timeout,
self._reservation)
else:
@@ -109,11 +111,12 @@ class MUSICLauncher(object):
timeout_str = str(self._timeout).replace(' ', '_')
# extract the multiprocess RNG seed to use or generate one if needed
- rng_seed = exd.rngSeed if exd.rngSeed is not None else random.randint(1, sys.maxint)
+ rng_seed = self.__exc.rngSeed if self.__exc.rngSeed is not None else \
+ random.randint(1, sys.maxint)
# build a MUSIC configuration script with correct brain ports, launchers and arugments
# save it to the host launcher temp directory, this is the same for every host
- music_conf = bibi_music_config.MUSICConfiguration(bibi)
+ music_conf = bibi_music_config.MUSICConfiguration(self.__bibi)
music_conf.add_application('CLE',
cle_launcher,
['--exdconf={}'.format(self._exd_file),
@@ -123,14 +126,13 @@ class MUSICLauncher(object):
'--reservation={}'.format(reservation_str),
'--sim-id={}'.format(self._sim_id),
'--timeout={}'.format(timeout_str),
- '--rng-seed={}'.format(rng_seed),
- '--music'],
+ '--rng-seed={}'.format(rng_seed)],
1)
music_conf.add_application('BRAIN',
brain_launcher,
['--bibi-file={}'.format(self._bibi_file),
'--rng-seed={}'.format(rng_seed)],
- exd.bibiConf.processes)
+ self.__exc.bibiConf.processes)
music_conf.save(self._launcher.local_tmpdir)
# deploy the generated configuration files / launch scripts to the target host
@@ -138,18 +140,24 @@ class MUSICLauncher(object):
# build an mpi launch command for the requested host configuration, currently we launch
# all processes on the same host
- self.cle_server = MUSICMPILauncher()
- self.cle_server.add_host(self._launcher.hostname,
- self._launcher.host_tmpdir,
- exd.bibiConf.processes + 1)
+ self.mpilauncher = MUSICMPILauncher()
+ self.mpilauncher.add_host(self._launcher.hostname,
+ self._launcher.host_tmpdir,
+ self.__exc.bibiConf.processes + 1)
# construct the mpi command line with the above host/launch information
- self.cle_server.build()
+ self.mpilauncher.build()
# for error propagation reasons, we have to launch and init the MPI processes to emulate
# the behavior of the single process launcher, if the mpirun command fails or the CLE/brain
# processes fail then the error will be properly propagated
- self.cle_server.launch()
+ self.mpilauncher.launch()
+
+ def run(self):
+ """
+ Runs the assembled simulation
+ """
+ self.mpilauncher.run()
def shutdown(self):
"""
@@ -157,9 +165,9 @@ class MUSICLauncher(object):
"""
# terminate the mpirun command (if it is still running)
- if self.cle_server:
- self.cle_server.shutdown()
- self.cle_server = None
+ if self.mpilauncher is not None:
+ self.mpilauncher.shutdown()
+ self.mpilauncher = None
# perform any launcher host specific cleanup
if self._launcher:
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/host/LocalLauncher.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/host/LocalLauncher.py
index 93ca47e3d80072a4fc8d1d252c744c61fa56380b..d9d6b43bc72c706425c95235c70776982ea23317 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/host/LocalLauncher.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/launch/host/LocalLauncher.py
@@ -67,7 +67,7 @@ class LocalLauncher(IHostLauncher):
"""
# create .sh launcher scripts for the CLE and brain processes
cle_launcher = self._create_launch_script('music_cle_launcher.sh',
- 'hbp_nrp_cleserver.server.CLELauncher')
+ 'hbp_nrp_music_interface.launch.MUSICCLEProcess')
brain_launcher = self._create_launch_script('music_brain_launcher.sh',
'hbp_nrp_music_interface.launch.' +
'MUSICBrainProcess')
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_brain_loader.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_brain_loader.py
index 65b567a55d6c9693c9d63a9422117582a0cca7aa..7b51fb9ee39b5fac99abb5c9c659f91f51321583 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_brain_loader.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_brain_loader.py
@@ -25,7 +25,7 @@ import unittest
from hbp_nrp_music_interface.cle.MUSICBrainLoader import load_proxies_from_xml
import hbp_nrp_cle.tf_framework.config as tf_config
-from hbp_nrp_cle.brainsim.pynn import simulator as sim
+import pyNN.nest as sim
from mock import Mock, patch
import os
@@ -53,7 +53,7 @@ class TestBrainLoader(unittest.TestCase):
self.assertRaises(Exception, load_proxies_from_xml, 'foo.xml', bar='foo')
@patch('__builtin__.open', spec=open)
- @patch('hbp_nrp_cle.brainsim.pynn.simulator.PopulationView', new=Mock(return_value='fake'))
+ @patch('pyNN.nest.PopulationView', new=Mock(return_value='fake'))
@patch('hbp_nrp_music_xml.pynn.xml_factory.XmlFactory.create_proxies',
new=Mock(return_value={'bar_to_brain': 'foo', 'bar_to_cle': 'bar'}))
def test_proxy_dict_valid(self, mock_open):
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_communication_adapter.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_communication_adapter.py
index b6aedc953f661a5a1c5bca1e194f1419e6caba11..14e345e472efe0dd6a090860664f85882d429ce6 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_communication_adapter.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_communication_adapter.py
@@ -50,8 +50,8 @@ class MockPopulationView(object):
@patch('hbp_nrp_cle.brainsim.pynn_nest.PyNNNestCommunicationAdapter.PyNNNestCommunicationAdapter.initialize')
@patch('hbp_nrp_cle.brainsim.pynn_nest.PyNNNestCommunicationAdapter.PyNNNestCommunicationAdapter.register_spike_source')
@patch('hbp_nrp_cle.brainsim.pynn_nest.PyNNNestCommunicationAdapter.PyNNNestCommunicationAdapter.register_spike_sink')
-@patch('hbp_nrp_cle.brainsim.pynn.simulator.PopulationView', MockPopulationView)
-@patch('hbp_nrp_cle.brainsim.pynn.simulator.Population', MockPopulation)
+@patch('pyNN.nest.PopulationView', MockPopulationView)
+@patch('pyNN.nest.Population', MockPopulation)
class TestCommunicationAdapter(unittest.TestCase):
def setUp(self):
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_control_adapter.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_control_adapter.py
index 4dcfa2a2ff9d7ab791ce21c504b733fb65bea5d0..3d054fc3a52afa3c58e72b2abe831dc9b6b23548 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_control_adapter.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/cle/test_control_adapter.py
@@ -39,7 +39,7 @@ class MockedMUSICSetup(object):
class TestControlAdapter(unittest.TestCase):
def test_missing_xml(self):
- mc = MUSICPyNNControlAdapter()
+ mc = MUSICPyNNControlAdapter(Mock())
self.assertRaises(Exception, mc.load_brain, 'foo.xml')
@patch('music.Setup', name=MockedMUSICSetup())
@@ -51,7 +51,7 @@ class TestControlAdapter(unittest.TestCase):
m.return_value.read.return_value = 'mock brain source'
with patch('__builtin__.open', m, create=True):
- mc = MUSICPyNNControlAdapter()
+ mc = MUSICPyNNControlAdapter(Mock())
mc.load_brain('foo.xml')
mocked_environ.assert_called_once_with('NRP_MUSIC_DIRECTORY')
diff --git a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/launch/test_music_launcher.py b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/launch/test_music_launcher.py
index ae7945af936acac92a34b1847d25a95318cd6dfc..c94af48fd0423c5cca430f5e6b6f90712996af09 100644
--- a/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/launch/test_music_launcher.py
+++ b/hbp_nrp_music_interface/hbp_nrp_music_interface/tests/launch/test_music_launcher.py
@@ -51,29 +51,34 @@ class TestMUSICLauncher(unittest.TestCase):
@patch('os.environ.get', return_value='')
def setUp(self, mock_environ_get):
- self.__launcher = MUSICLauncher('exd_conf', 'bibi_file', 'env_file', '/exp_path',
- 'local', None, 1, '1234 T 567')
+ exc_mock = Mock()
+ exc_mock.path = 'exd_conf'
+ exc_mock.dir = '/exp_path'
+ exc_mock.rngSeed = 123456
+ exc_mock.bibiConf.processes = 10
+ bibi_mock = Mock()
+ bibi_mock.path = 'bibi_file'
+ self.__launcher = MUSICLauncher(1, exc_mock, bibi_mock,
+ gzserver_host='local',
+ reservation=None,
+ timeout=None)
@patch('hbp_nrp_music_interface.launch.MUSICLauncher.LocalLauncher', MockLocalLauncher)
@patch('hbp_nrp_music_interface.launch.MUSICLauncher.bibi_music_config.MUSICConfiguration')
@patch('hbp_nrp_music_interface.launch.MUSICLauncher.MUSICMPILauncher')
def test_init(self, mock_mpi, mock_conf):
-
- # mock the ExDConf and parameters
- exd = Mock()
- exd.rngSeed = 123456
- exd.bibiConf.processes = 10
-
# mock all of the local launcher functionality
- self.__launcher.init('bibi', exd)
+ with patch('hbp_nrp_music_interface.launch.MUSICLauncher.os.environ.get',
+ return_value='/somewhere/over/the/rainbow'):
+ self.__launcher.initialize('env_file', None)
# call to generate launch scripts
self.__launcher._launcher.deploy.assert_called_once()
# assert that all of the MPI configuration/launch commands were called
- self.__launcher.cle_server.add_host.assert_called_once_with('localhost', '/mock_host_tmpdir', 11)
- self.__launcher.cle_server.build.assert_called_once()
- self.__launcher.cle_server.launch.assert_called_once()
+ self.__launcher.mpilauncher.add_host.assert_called_once_with('localhost', '/mock_host_tmpdir', 11)
+ self.__launcher.mpilauncher.build.assert_called_once()
+ self.__launcher.mpilauncher.launch.assert_called_once()
@patch('os.system')
def test_shutdown(self, system_mock):
@@ -85,7 +90,7 @@ class TestMUSICLauncher(unittest.TestCase):
mock_launcher.shutdown = Mock()
# set values like in init() and shutdown
- self.__launcher.cle_server = mock_cle_server
+ self.__launcher.mpilauncher = mock_cle_server
self.__launcher._launcher = mock_launcher
self.__launcher.shutdown()
@@ -94,7 +99,7 @@ class TestMUSICLauncher(unittest.TestCase):
mock_launcher.shutdown.assert_called_once()
# verify the local variables are unset
- self.assertEqual(self.__launcher.cle_server, None)
+ self.assertEqual(self.__launcher.mpilauncher, None)
self.assertEqual(self.__launcher._launcher, None)
# verify the ros cleanup command has been called