def test_init_fail(self): try: Config(None, "path", None) self.fail("expected Exception") except MultiProjectException: pass try: Config([PathSpec('foo', 'bar')], "path", None) self.fail("expected Exception") except MultiProjectException: pass
def test_source_setup_sh(self): test_folder = os.path.join(self.test_root_path, 'workspacetest') os.makedirs(test_folder) othersetupfile = os.path.join(test_folder, 'othersetup.sh') testsetupfile = os.path.join(test_folder, 'testsetup.sh') with open(othersetupfile, 'w') as fhand: fhand.write('unset ROS_WORKSPACE') config = Config([ PathSpec(self.ros_path), PathSpec(othersetupfile, scmtype=None, tags=['setup-file']) ], install_path=test_folder, config_filename=ROSINSTALL_FILENAME) result = rosinstall.setupfiles.generate_setup_sh_text( config.get_base_path()) self.assertTrue('export ROS_WORKSPACE=%s' % test_folder in result) with open(testsetupfile, 'w') as fhand: fhand.write(result) # check that sourcing setup.sh raises error when .wstool is missing raised = False try: subprocess.check_call(". %s" % testsetupfile, shell=True, env=self.new_environ) except: raised = True self.assertTrue(raised, 'sourcing setup.sh with missing .wstool should fail') # test that our otherscript really unsets ROS_WORKSPACE, else nexttest would be invalid # using basename to check var is not set raised = False try: cmd = "export ROS_WORKSPACE=foo && . %s && basename $ROS_WORKSPACE" % othersetupfile subprocess.check_call(cmd, shell=True, env=self.new_environ) except: raised = True self.assertTrue(raised, 'unsetting-sh-file did not unset var') # now test that when sourcing setup.sh that contains a # setup-file to other sh file which unsets ROS_WORKSPACE, # ROS_WORKSPACE is still set in the end generate_config_yaml(config, ROSINSTALL_FILENAME, '') self.assertTrue( os.path.isfile(os.path.join(test_folder, ROSINSTALL_FILENAME))) # using basename to check var is set cmd = "export ROS_WORKSPACE=foo && . %s && echo $ROS_WORKSPACE" % testsetupfile po = subprocess.Popen(cmd, shell=True, cwd=test_folder, stdout=subprocess.PIPE) workspace = po.stdout.read().decode('UTF-8').rstrip('"').lstrip( '"').strip() po.stdout.close() self.assertEqual(test_folder, workspace)
def test_mock_vcs_element(self): yaml = [] install_path = 'install/path' config_filename = '.filename' config = Config(yaml, install_path, config_filename) try: config._create_vcs_config_element('mock', None, None, None) fail("expected Exception") except MultiProjectException: pass config = Config(yaml, install_path, config_filename, {"mock": MockVcsConfigElement}) self.assertTrue( config._create_vcs_config_element('mock', None, None, None))
def get_config(basepath, additional_uris=None, config_filename=None, merge_strategy='KillAppend'): """ Create a Config element necessary for all other commands. The command will look at the uris in sequence, each can be a web resource, a filename or a folder. In case it is a folder, when a config_filename is provided, the folder will be searched for a file of that name, and that one will be used. Else the folder will be considered a target location for the config. All files will be parsed for config elements, thus conceptually the input to Config is an expanded list of config elements. Config takes this list and consolidates duplicate paths by keeping the last one in the list. :param basepath: where relative paths shall be resolved against :param additional_uris: the location of config specifications or folders :param config_filename: name of files which may be looked at for config information :param merge_strategy: One of 'KillAppend, 'MergeKeep', 'MergeReplace' :returns: a Config object :raises MultiProjectException: on plenty of errors """ if basepath is None: raise MultiProjectException("Need to provide a basepath for Config.") # print("source...........................", path_specs) ## Generate the config class with the uri and path if (config_filename is not None and basepath is not None and os.path.isfile(os.path.join(basepath, config_filename))): base_path_specs = get_path_specs_from_uri(os.path.join(basepath, config_filename), as_is=True) else: base_path_specs = [] config = Config(base_path_specs, basepath, config_filename=config_filename, merge_strategy=merge_strategy) add_uris(config=config, additional_uris=additional_uris, config_filename=config.get_config_filename(), merge_strategy=merge_strategy) return config
def get_config(basepath, additional_uris=None, config_filename=None, merge_strategy='KillAppend'): """ Create a Config element necessary for all other commands. The command will look at the uris in sequence, each can be a web resource, a filename or a folder. In case it is a folder, when a config_filename is provided, the folder will be searched for a file of that name, and that one will be used. Else the folder will be considered a target location for the config. All files will be parsed for config elements, thus conceptually the input to Config is an expanded list of config elements. Config takes this list and consolidates duplicate paths by keeping the last one in the list. :param basepath: where relative paths shall be resolved against :param additional_uris: the location of config specifications or folders :param config_filename: name of files which may be looked at for config information :param merge_strategy: One of 'KillAppend, 'MergeKeep', 'MergeReplace' :returns: a Config object :raises MultiProjectException: on plenty of errors """ if basepath is None: raise MultiProjectException("Need to provide a basepath for Config.") # print("source...........................", path_specs) ## Generate the config class with the uri and path if (config_filename is not None and basepath is not None and os.path.isfile(os.path.join(basepath, config_filename))): base_path_specs = get_path_specs_from_uri(os.path.join( basepath, config_filename), as_is=True) else: base_path_specs = [] config = Config(base_path_specs, basepath, config_filename=config_filename, merge_strategy=merge_strategy) add_uris(config=config, additional_uris=additional_uris, config_filename=config.get_config_filename(), merge_strategy=merge_strategy) return config
def test_init(self): yaml = [] install_path = '/install/path' config_filename = '.filename' config = Config(yaml, install_path, config_filename) self.assertEqual(install_path, config.get_base_path()) self.assertEqual([], config.get_config_elements()) config = Config([ PathSpec("foo"), PathSpec(os.path.join(_test_root, "example_dirs", "ros_comm")), PathSpec(os.path.join(_test_root, "example_dirs", "ros")), PathSpec(os.path.join(_test_root, "example_dirs", "roscpp")), PathSpec("bar") ], ".", None) self.assertEqual(os.path.abspath('.'), config.get_base_path())
def test_gen_python_code_python3(self): # requires python3 to be installed, obviously config = Config([ PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar.sh", tags=['setup-file']), PathSpec("baz") ], self.directory, None) wstool.config_yaml.generate_config_yaml(config, '.rosinstall', '') filename = os.path.join(self.directory, "test_gen.py") _add_to_file(filename, rosinstall.setupfiles.generate_embedded_python()) sh_filename = os.path.join(self.directory, "bar.sh") _add_to_file(sh_filename, "#! /usr/bin/env sh") cmd = "python3 -W ignore %s" % filename p = subprocess.Popen(cmd, shell=True, cwd=self.directory, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = p.communicate() self.assertEqual(''.encode('UTF-8'), err, err) self.assertTrue( '/test/example_dirs/ros_comm'.encode('UTF-8') in output, output) self.assertTrue('baz'.encode('UTF-8') in output, output) self.assertTrue( 'ROSINSTALL_PATH_SETUPFILE_SEPARATOR'.encode('UTF-8') in output, output) self.assertTrue(output.endswith('/bar.sh\n'.encode('UTF-8')), output)
def test_mock_install_fail(self): test_root = os.path.realpath(tempfile.mkdtemp()) try: # robust git1 = PathSpec('foo', 'git', 'git/uri', 'git.version') svn1 = PathSpec('foos', 'svn', 'svn/uri', '12345') hg1 = PathSpec('fooh', 'hg', 'hg/uri', 'hg.version') bzr1 = PathSpec('foob', 'bzr', 'bzr/uri', 'bzr.version') config = Config( [git1, svn1, hg1, bzr1], install_path=test_root, config_filename=None, extended_types={ "svn": MockVcsConfigElement, "git": MockVcsConfigElement, "hg": MockVcsConfigElement, "bzr": MockVcsConfigElement }) config.get_config_elements()[1].install_success = False wstool.multiproject_cmd.cmd_install_or_update(config, robust=True) try: wstool.multiproject_cmd.cmd_install_or_update(config, robust=False) self.fail("expected Exception") except MultiProjectException: pass finally: shutil.rmtree(test_root)
def test_gen_setupsh(self): config = Config([PathSpec(self.ros_path), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar")], self.test_root_path, None) result = rosinstall.setupfiles.generate_setup_sh_text(config.get_base_path()) self.assertTrue(result.count("#!/usr/bin/env sh") == 1) config = Config([PathSpec(self.ros_path), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar.sh", tags=['setup-file'])], self.test_root_path, None) result = rosinstall.setupfiles.generate_setup_sh_text(config.get_base_path()) self.assertTrue(result.count("#!/usr/bin/env sh") == 1, result)
def test_mock_install(self): test_root = os.path.realpath(tempfile.mkdtemp()) try: git1 = PathSpec('foo', 'git', 'git/uri', 'git.version') svn1 = PathSpec('foos', 'svn', 'svn/uri', '12345') hg1 = PathSpec('fooh', 'hg', 'hg/uri', 'hg.version') bzr1 = PathSpec('foob', 'bzr', 'bzr/uri', 'bzr.version') config = Config( [git1, svn1, hg1, bzr1], test_root, None, { "svn": MockVcsConfigElement, "git": MockVcsConfigElement, "hg": MockVcsConfigElement, "bzr": MockVcsConfigElement }) wstool.multiproject_cmd.cmd_install_or_update(config) wstool.multiproject_cmd.cmd_install_or_update(config) wstool.multiproject_cmd.cmd_install_or_update(config, num_threads=10) wstool.multiproject_cmd.cmd_install_or_update(config, num_threads=10) wstool.multiproject_cmd.cmd_install_or_update(config, num_threads=1) wstool.multiproject_cmd.cmd_install_or_update(config, num_threads=1) finally: shutil.rmtree(test_root)
def test_source_setup_sh(self): test_folder = os.path.join(self.test_root_path, 'workspacetest') os.makedirs(test_folder) othersetupfile = os.path.join(test_folder, 'othersetup.sh') testsetupfile = os.path.join(test_folder, 'testsetup.sh') with open(othersetupfile, 'w') as fhand: fhand.write('unset ROS_WORKSPACE') config = Config([PathSpec(self.ros_path), PathSpec(othersetupfile, scmtype=None, tags=['setup-file'])], install_path=test_folder, config_filename=ROSINSTALL_FILENAME) result = rosinstall.setupfiles.generate_setup_sh_text(config.get_base_path()) self.assertTrue('export ROS_WORKSPACE=%s' % test_folder in result) with open(testsetupfile, 'w') as fhand: fhand.write(result) # check that sourcing setup.sh raises error when .wstool is missing raised = False try: subprocess.check_call(". %s" % testsetupfile , shell=True, env=self.new_environ) except: raised = True self.assertTrue(raised, 'sourcing setup.sh with missing .wstool should fail') # test that our otherscript really unsets ROS_WORKSPACE, else nexttest would be invalid # using basename to check var is not set raised = False try: cmd = "export ROS_WORKSPACE=foo && . %s && basename $ROS_WORKSPACE" % othersetupfile subprocess.check_call( cmd, shell=True, env=self.new_environ) except: raised = True self.assertTrue(raised, 'unsetting-sh-file did not unset var') # now test that when sourcing setup.sh that contains a # setup-file to other sh file which unsets ROS_WORKSPACE, # ROS_WORKSPACE is still set in the end generate_config_yaml(config, ROSINSTALL_FILENAME, '') self.assertTrue(os.path.isfile(os.path.join(test_folder, ROSINSTALL_FILENAME))) # using basename to check var is set cmd = "export ROS_WORKSPACE=foo && . %s && echo $ROS_WORKSPACE" % testsetupfile po = subprocess.Popen(cmd, shell=True, cwd=test_folder, stdout=subprocess.PIPE) workspace = po.stdout.read().decode('UTF-8').rstrip('"').lstrip('"').strip() po.stdout.close() self.assertEqual(test_folder, workspace)
def test_get_ros_package_path(self): config = Config([PathSpec("foo"), PathSpec("bar")], ".", None) self.assertEqual(list(map(os.path.abspath, ['bar', 'foo'])), wstool.helpers.get_ros_package_path(config))
def test_get_ros_stack_path(self): config = Config([ PathSpec("foo"), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec(os.path.join("test", "example_dirs", "roscpp")), PathSpec("bar") ], ".", None) self.assertEqual(None, rosinstall.helpers.get_ros_stack_path(config)) config = Config([ PathSpec("foo"), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec(os.path.join("test", "example_dirs", "ros")), PathSpec(os.path.join("test", "example_dirs", "roscpp")), PathSpec("bar") ], ".", None) self.assertEqual(os.path.abspath("test/example_dirs/ros"), rosinstall.helpers.get_ros_stack_path(config))
def _get_mock_config(self, yaml, install_path='/install/path', merge_strategy="KillAppend"): config_filename = '.filename' return Config(yaml, install_path, config_filename, {"mock": MockVcsConfigElement}, merge_strategy=merge_strategy)
def test_get_ros_package_path(self): config = Config([], "/test/example_dirs", None) self.assertEqual([], rosinstall.helpers.get_ros_package_path(config)) config = Config([PathSpec("foo")], "/test/example_dirs", None) self.assertEqual(['/test/example_dirs/foo'], rosinstall.helpers.get_ros_package_path(config)) config = Config([ PathSpec("foo"), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec(os.path.join("test", "example_dirs", "ros")), PathSpec(os.path.join("test", "example_dirs", "roscpp")), PathSpec("bar") ], ".", None) self.assertEqual( list( map(os.path.abspath, [ 'bar', 'test/example_dirs/roscpp', 'test/example_dirs/ros_comm', 'foo' ])), rosinstall.helpers.get_ros_package_path(config))
def test_gen_setup(self): try: config = Config([ PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar") ], self.test_root_path, None) rosinstall.setupfiles.generate_setup(config) self.fail('expected exception') except ROSInstallException: pass config = Config([ PathSpec(self.ros_path), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar") ], self.test_root_path, None) rosinstall.setupfiles.generate_setup(config) self.assertTrue( os.path.isfile(os.path.join(self.test_root_path, 'setup.sh'))) self.assertTrue( os.path.isfile(os.path.join(self.test_root_path, 'setup.bash'))) self.assertTrue( os.path.isfile(os.path.join(self.test_root_path, 'setup.zsh')))
def test_gen_setup_bash(self): config = Config([ PathSpec(self.ros_path), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar") ], self.test_root_path, None) result = rosinstall.setupfiles.generate_setup_bash_text('bash') self.assertTrue(result.count("#!/usr/bin/env bash") == 1) self.assertTrue(result.count("CATKIN_SHELL=bash") == 1) self.assertTrue( result.count("ROSSHELL_PATH=`rospack find rosbash`/rosbash") == 1) result = rosinstall.setupfiles.generate_setup_bash_text('zsh') self.assertTrue(result.count("#!/usr/bin/env zsh") == 1) self.assertTrue(result.count("CATKIN_SHELL=zsh") == 1) self.assertTrue( result.count("ROSSHELL_PATH=`rospack find rosbash`/roszsh") == 1)
def test_get_stack_element_in_config(self): self.test_root_path = tempfile.mkdtemp() self.install_path = os.path.join(self.test_root_path, "install") os.makedirs(self.install_path) f = io.open(os.path.join(self.install_path, 'stack.xml'), 'a') f.write(unicode("hello stack")) f.close() config = Config( [PathSpec("foo"), PathSpec("install"), PathSpec("bar")], self.test_root_path, None) self.assertEqual( None, rosinstall.rosws_stacks_cli.get_stack_element_in_config( config, 'foo')) self.assertEqual( None, rosinstall.rosws_stacks_cli.get_stack_element_in_config( config, None)) el = rosinstall.rosws_stacks_cli.get_stack_element_in_config( config, 'install') self.assertEqual(self.install_path, el.get_path()) shutil.rmtree(self.test_root_path)
def test_gen_setupsh(self): config = Config([ PathSpec(self.ros_path), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar") ], self.test_root_path, None) result = rosinstall.setupfiles.generate_setup_sh_text( config.get_base_path()) self.assertTrue(result.count("#!/usr/bin/env sh") == 1) config = Config([ PathSpec(self.ros_path), PathSpec(os.path.join("test", "example_dirs", "ros_comm")), PathSpec("bar.sh", tags=['setup-file']) ], self.test_root_path, None) result = rosinstall.setupfiles.generate_setup_sh_text( config.get_base_path()) self.assertTrue(result.count("#!/usr/bin/env sh") == 1, result)
def test_source_setup_sh_chain(self): """ Tests chaining of workspaces, which is fragile because sourcing very similar setup.sh files recursively """ chain_root_path = os.path.join(self.test_root_path, 'chaintest') os.makedirs(chain_root_path) test_folder1 = os.path.join(chain_root_path, 'ws1') os.makedirs(test_folder1) test_folder2 = os.path.join(chain_root_path, 'ws2') os.makedirs(test_folder2) test_folder3 = os.path.join(chain_root_path, 'ws3') os.makedirs(test_folder3) test_folder4 = os.path.join(chain_root_path, 'ws4') os.makedirs(test_folder4) othersetupfile = os.path.join(chain_root_path, 'othersetup.sh') with open(othersetupfile, 'w') as fhand: fhand.write('export ROS_PACKAGE_PATH=/opt/ros/distro') config1 = Config([ PathSpec('ws1sub'), PathSpec(os.path.join(test_folder2, "setup.sh"), scmtype=None, tags=['setup-file']), PathSpec(os.path.join(test_folder4, "setup.sh"), scmtype=None, tags=['setup-file']) ], install_path=test_folder1, config_filename=ROSINSTALL_FILENAME) config2 = Config([ PathSpec('ws2sub'), PathSpec(os.path.join(test_folder3, "setup.sh"), scmtype=None, tags=['setup-file']) ], install_path=test_folder2, config_filename=ROSINSTALL_FILENAME) config3 = Config([ PathSpec('ws3sub'), PathSpec(othersetupfile, scmtype=None, tags=['setup-file']) ], install_path=test_folder3, config_filename=ROSINSTALL_FILENAME) config4 = Config([PathSpec('ws4sub')], install_path=test_folder4, config_filename=ROSINSTALL_FILENAME) cmd_generate_ros_files(config1, test_folder1, no_ros_allowed=True) cmd_persist_config(config1, os.path.join(test_folder1, ROSINSTALL_FILENAME)) cmd_generate_ros_files(config2, test_folder2, no_ros_allowed=True) cmd_persist_config(config2, os.path.join(test_folder2, ROSINSTALL_FILENAME)) cmd_generate_ros_files(config3, test_folder3, no_ros_allowed=True) cmd_persist_config(config3, os.path.join(test_folder3, ROSINSTALL_FILENAME)) cmd_generate_ros_files(config4, test_folder4, no_ros_allowed=True) cmd_persist_config(config4, os.path.join(test_folder4, ROSINSTALL_FILENAME)) cmd = ". %s && echo $ROS_PACKAGE_PATH" % os.path.join( test_folder1, "setup.sh") po = subprocess.Popen(cmd, shell=True, cwd=test_folder1, stdout=subprocess.PIPE) ppath = po.stdout.read().decode('UTF-8').strip('"').strip() po.stdout.close() expected = ':'.join([ os.path.join(test_folder1, "ws1sub"), os.path.join(test_folder2, "ws2sub"), os.path.join(test_folder3, "ws3sub"), os.path.join(test_folder4, "ws4sub"), '/opt/ros/distro' ]) self.assertEqual(expected, ppath) # test double sourcing cmd = ". %s ; . %s && echo $ROS_PACKAGE_PATH" % (os.path.join( test_folder2, "setup.sh"), os.path.join(test_folder4, "setup.sh")) po = subprocess.Popen(cmd, shell=True, cwd=test_folder1, stdout=subprocess.PIPE) ppath = po.stdout.read().decode('UTF-8').strip('"').strip() po.stdout.close() expected = os.path.join(test_folder4, "ws4sub") self.assertEqual(expected, ppath)