def test_toolchain(self): """Test whether toolchain is initialized correctly.""" test_ecs = os.path.join('test', 'framework', 'easyconfigs', 'test_ecs') ec_file = find_full_path(os.path.join(test_ecs, 'g', 'gzip', 'gzip-1.4.eb')) ec = EasyConfig(ec_file, validate=False) tc = ec.toolchain self.assertTrue('debug' in tc.options)
def test_toolchain(self): """Test whether toolchain is initialized correctly.""" ec_file = find_full_path( os.path.join('test', 'framework', 'easyconfigs', 'gzip-1.4.eb')) ec = EasyConfig(ec_file, validate=False) tc = ec.toolchain self.assertTrue('debug' in tc.options)
def legacySetUp(self): self.log.deprecated("legacySetUp", "2.0") cfg_path = os.path.join("easybuild", "easybuild_config.py") cfg_full_path = find_full_path(cfg_path) self.assertTrue(cfg_full_path) config.oldstyle_init(cfg_full_path) self.cwd = os.getcwd()
def legacySetUp(self): self.log.deprecated("legacySetUp", "2.0") cfg_path = os.path.join('easybuild', 'easybuild_config.py') cfg_full_path = find_full_path(cfg_path) self.assertTrue(cfg_full_path) config.oldstyle_init(cfg_full_path) self.cwd = os.getcwd()
def setUp(self): """Set up everything for a unit test.""" # initialize configuration so config.get_modules_tool function works eb_go = eboptions.parse_options() config.init(eb_go.options, eb_go.get_options_by_section('config')) # make sure path with modules for testing is added to MODULEPATH self.orig_modpath = os.environ.get('MODULEPATH', '') os.environ['MODULEPATH'] = find_full_path(os.path.join('test', 'framework', 'modules'))
def setUp(self): """Set up everything for a unit test.""" super(ToolchainTest, self).setUp() # start with a clean slate modules.modules_tool().purge() # make sure path with modules for testing is added to MODULEPATH self.orig_modpath = os.environ.get('MODULEPATH', '') os.environ['MODULEPATH'] = find_full_path(os.path.join('test', 'framework', 'modules'))
def setUp(self): """Set up everything for a unit test.""" super(ToolchainTest, self).setUp() # start with a clean slate modules.modules_tool().purge() # make sure path with modules for testing is added to MODULEPATH self.orig_modpath = os.environ.get('MODULEPATH', '') os.environ['MODULEPATH'] = find_full_path( os.path.join('test', 'framework', 'modules'))
def setUp(self): """Set up everything for a unit test.""" super(RobotTest, self).setUp() # replace Modules class with something we have control over config.modules_tool = mock_module ectools.modules_tool = mock_module os.environ['module'] = "() { eval `/bin/echo $*`\n}" self.base_easyconfig_dir = find_full_path(os.path.join("test", "framework", "easyconfigs")) self.assertTrue(self.base_easyconfig_dir)
def setUp(self): """Set up everything for a unit test.""" # initialize configuration so config.get_modules_tool function works eb_go = eboptions.parse_options() config.init(eb_go.options, eb_go.get_options_by_section('config')) # start with a clean slate modules.modules_tool().purge() # make sure path with modules for testing is added to MODULEPATH self.orig_modpath = os.environ.get('MODULEPATH', '') os.environ['MODULEPATH'] = find_full_path( os.path.join('test', 'framework', 'modules'))
def setUp(self): """ initialize ModuleGenerator with test Application """ super(ModuleGeneratorTest, self).setUp() # find .eb file eb_path = os.path.join(os.path.join(os.path.dirname(__file__), 'easyconfigs'), 'gzip-1.4.eb') eb_full_path = find_full_path(eb_path) self.assertTrue(eb_full_path) ec = EasyConfig(eb_full_path) self.eb = EasyBlock(ec) self.modgen = ModuleGenerator(self.eb) self.modgen.app.installdir = tempfile.mkdtemp(prefix='easybuild-modgen-test-') self.orig_module_naming_scheme = config.get_module_naming_scheme()
def setUp(self): """ dynamically replace Modules class with MockModule """ # replace Modules class with something we have control over config.modules_tool = mock_module main.modules_tool = mock_module self.log = fancylogger.getLogger("RobotTest", fname=False) # redefine the main log when calling the main functions directly main._log = fancylogger.getLogger("main", fname=False) self.cwd = os.getcwd() self.base_easyconfig_dir = find_full_path(os.path.join("test", "framework", "easyconfigs")) self.assertTrue(self.base_easyconfig_dir)
def setUp(self): """ dynamically replace Modules class with MockModule """ # replace Modules class with something we have control over modules.Modules = MockModule main.Modules = MockModule self.log = fancylogger.getLogger("RobotTest", fname=False) # redefine the main log when calling the main functions directly main._log = fancylogger.getLogger("main", fname=False) self.cwd = os.getcwd() self.base_easyconfig_dir = find_full_path(os.path.join("test", "framework", "easyconfigs")) self.assertTrue(self.base_easyconfig_dir)
def setUp(self): """Test setup.""" super(ModuleGeneratorTest, self).setUp() # find .eb file eb_path = os.path.join(os.path.join(os.path.dirname(__file__), 'easyconfigs'), 'gzip-1.4.eb') eb_full_path = find_full_path(eb_path) self.assertTrue(eb_full_path) ec = EasyConfig(eb_full_path) self.eb = EasyBlock(ec) self.modgen = self.MODULE_GENERATOR_CLASS(self.eb) self.modgen.app.installdir = tempfile.mkdtemp(prefix='easybuild-modgen-test-') self.orig_module_naming_scheme = config.get_module_naming_scheme()
def setUp(self): """Test setup.""" super(ModuleGeneratorTest, self).setUp() # find .eb file topdir = os.path.dirname(os.path.abspath(__file__)) eb_path = os.path.join(topdir, 'easyconfigs', 'test_ecs', 'g', 'gzip', 'gzip-1.4.eb') eb_full_path = find_full_path(eb_path) self.assertTrue(eb_full_path) ec = EasyConfig(eb_full_path) self.eb = EasyBlock(ec) self.modgen = self.MODULE_GENERATOR_CLASS(self.eb) self.modgen.app.installdir = tempfile.mkdtemp(prefix='easybuild-modgen-test-') self.orig_module_naming_scheme = config.get_module_naming_scheme()
def setUp(self): """Set up everything for a unit test.""" # initialize configuration so config.get_modules_tool function works eb_go = eboptions.parse_options() config.init(eb_go.options, eb_go.get_options_by_section('config')) # replace Modules class with something we have control over config.modules_tool = mock_module ectools.modules_tool = mock_module self.log = fancylogger.getLogger("RobotTest", fname=False) self.cwd = os.getcwd() self.base_easyconfig_dir = find_full_path(os.path.join("test", "framework", "easyconfigs")) self.assertTrue(self.base_easyconfig_dir)
def setUp(self): """ initialize ModuleGenerator with test Application """ super(ModuleGeneratorTest, self).setUp() # find .eb file eb_path = os.path.join( os.path.join(os.path.dirname(__file__), 'easyconfigs'), 'gzip-1.4.eb') eb_full_path = find_full_path(eb_path) self.assertTrue(eb_full_path) ec = EasyConfig(eb_full_path) self.eb = EasyBlock(ec) self.modgen = ModuleGenerator(self.eb) self.modgen.app.installdir = tempfile.mkdtemp( prefix='easybuild-modgen-test-') self.orig_module_naming_scheme = config.get_module_naming_scheme()
def setUp(self): """Set up everything for a unit test.""" # initialize configuration so config.get_modules_tool function works eb_go = eboptions.parse_options() config.init(eb_go.options, eb_go.get_options_by_section('config')) # replace Modules class with something we have control over config.modules_tool = mock_module main.modules_tool = mock_module self.log = fancylogger.getLogger("RobotTest", fname=False) # redefine the main log when calling the main functions directly main._log = fancylogger.getLogger("main", fname=False) self.cwd = os.getcwd() self.base_easyconfig_dir = find_full_path( os.path.join("test", "framework", "easyconfigs")) self.assertTrue(self.base_easyconfig_dir)
def test_obtain_easyconfig(self): """test obtaining an easyconfig file given certain specifications""" tcname = 'GCC' tcver = '4.3.2' patches = ["one.patch"] # prepare a couple of eb files to test again fns = ["pi-3.14.eb", "pi-3.13-GCC-4.3.2.eb", "pi-3.15-GCC-4.3.2.eb", "pi-3.15-GCC-4.4.5.eb", "foo-1.2.3-GCC-4.3.2.eb"] eb_files = [(fns[0], "\n".join(['name = "pi"', 'version = "3.12"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "dummy", "version": "dummy"}', 'patches = %s' % patches ])), (fns[1], "\n".join(['name = "pi"', 'version = "3.13"', 'homepage = "http://google.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'patches = %s' % patches ])), (fns[2], "\n".join(['name = "pi"', 'version = "3.15"', 'homepage = "http://google.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'patches = %s' % patches ])), (fns[3], "\n".join(['name = "pi"', 'version = "3.15"', 'homepage = "http://google.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "4.5.1"}' % tcname, 'patches = %s' % patches ])), (fns[4], "\n".join(['name = "foo"', 'version = "1.2.3"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver) ])) ] self.ec_dir = tempfile.mkdtemp() for (fn, txt) in eb_files: write_file(os.path.join(self.ec_dir, fn), txt) # should crash when no suited easyconfig file (or template) is available specs = {'name': 'nosuchsoftware'} error_regexp = ".*No easyconfig files found for software %s, and no templates available. I'm all out of ideas." % specs['name'] self.assertErrorRegex(EasyBuildError, error_regexp, obtain_ec_for, specs, [self.ec_dir], None) # should find matching easyconfig file specs = {'name': 'foo', 'version': '1.2.3'} res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], False) self.assertEqual(res[1], os.path.join(self.ec_dir, fns[-1])) # should not pick between multiple available toolchain names name = "pi" ver = "3.12" suff = "mysuff" specs.update({ 'name': name, 'version': ver, 'versionsuffix': suff }) error_regexp = ".*No toolchain name specified, and more than one available: .*" self.assertErrorRegex(EasyBuildError, error_regexp, obtain_ec_for, specs, [self.ec_dir], None) # should be able to generate an easyconfig file that slightly differs ver = '3.16' specs.update({ 'toolchain_name': tcname, 'toolchain_version': tcver, 'version': ver, 'foo': 'bar123' }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[1], "%s-%s-%s-%s%s.eb" % (name, ver, tcname, tcver, suff)) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['name'], specs['name']) self.assertEqual(ec['version'], specs['version']) self.assertEqual(ec['versionsuffix'], specs['versionsuffix']) self.assertEqual(ec['toolchain'], {'name': tcname, 'version': tcver}) # can't check for key 'foo', because EasyConfig ignores parameter names it doesn't know about txt = read_file(res[1]) self.assertTrue(re.search('foo = "%s"' % specs['foo'], txt)) os.remove(res[1]) # should pick correct version, i.e. not newer than what's specified, if a choice needs to be made ver = '3.14' specs.update({'version': ver}) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['version'], specs['version']) txt = read_file(res[1]) self.assertTrue(re.search("version = [\"']%s[\"'] .*was: [\"']3.13[\"']" % ver, txt)) os.remove(res[1]) # should pick correct toolchain version as well, i.e. now newer than what's specified, if a choice needs to be made specs.update({ 'version': '3.15', 'toolchain_version': '4.4.5', }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['version'], specs['version']) self.assertEqual(ec['toolchain']['version'], specs['toolchain_version']) txt = read_file(res[1]) pattern = "toolchain = .*version.*[\"']%s[\"'].*was: .*version.*[\"']%s[\"']" % (specs['toolchain_version'], tcver) self.assertTrue(re.search(pattern, txt)) os.remove(res[1]) # should be able to prepend to list of patches and handle list of dependencies new_patches = ['two.patch', 'three.patch'] deps = [('foo', '1.2.3'), ('bar', '666')] specs.update({ 'patches': new_patches[:], 'dependencies': deps }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['patches'], specs['patches']) self.assertEqual(ec['dependencies'], specs['dependencies']) os.remove(res[1]) # verify append functionality for lists specs['patches'].insert(0, '') res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['patches'], patches + new_patches) specs['patches'].remove('') os.remove(res[1]) # verify prepend functionality for lists specs['patches'].append('') res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['patches'], new_patches + patches) os.remove(res[1]) # should use supplied filename fn = "my.eb" res = obtain_ec_for(specs, [self.ec_dir], fn) self.assertEqual(res[0], True) self.assertEqual(res[1], fn) os.remove(res[1]) # should use a template if it's there tpl_path = os.path.join("share", "easybuild", "easyconfigs", "TEMPLATE.eb") def trim_path(path): dirs = path.split(os.path.sep) if len(dirs) > 3 and 'site-packages' in dirs: if path.endswith('.egg'): path = os.path.sep.join(dirs[:-4]) # strip of lib/python2.7/site-packages/*.egg part else: path = os.path.sep.join(dirs[:-3]) # strip of lib/python2.7/site-packages part return path tpl_full_path = find_full_path(tpl_path, trim=trim_path) # only run this test if the TEMPLATE.eb file is available # TODO: use unittest.skip for this (but only works from Python 2.7) if tpl_full_path: shutil.copy2(tpl_full_path, self.ec_dir) specs.update({'name': 'nosuchsoftware'}) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1], valid_stops=self.all_stops) self.assertEqual(ec['name'], specs['name']) os.remove(res[1]) # cleanup shutil.rmtree(self.ec_dir)
def setUp(self): """Setup for tests.""" # make sure path with modules for testing is added to MODULEPATH self.orig_modpath = os.environ.get('MODULEPATH', '') os.environ['MODULEPATH'] = find_full_path( os.path.join('test', 'framework', 'modules'))
def test_obtain_easyconfig(self): """test obtaining an easyconfig file given certain specifications""" tcname = 'GCC' tcver = '4.3.2' patches = ["one.patch"] # prepare a couple of eb files to test again fns = ["pi-3.14.eb", "pi-3.13-GCC-4.3.2.eb", "pi-3.15-GCC-4.3.2.eb", "pi-3.15-GCC-4.4.5.eb", "foo-1.2.3-GCC-4.3.2.eb"] eb_files = [(fns[0], "\n".join(['name = "pi"', 'version = "3.12"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "dummy", "version": "dummy"}', 'patches = %s' % patches ])), (fns[1], "\n".join(['name = "pi"', 'version = "3.13"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'patches = %s' % patches ])), (fns[2], "\n".join(['name = "pi"', 'version = "3.15"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'patches = %s' % patches ])), (fns[3], "\n".join(['name = "pi"', 'version = "3.15"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "4.5.1"}' % tcname, 'patches = %s' % patches ])), (fns[4], "\n".join(['name = "foo"', 'version = "1.2.3"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'foo_extra1 = "bar"', ])) ] self.ec_dir = tempfile.mkdtemp() for (fn, txt) in eb_files: write_file(os.path.join(self.ec_dir, fn), txt) # should crash when no suited easyconfig file (or template) is available specs = {'name': 'nosuchsoftware'} error_regexp = ".*No easyconfig files found for software %s, and no templates available. I'm all out of ideas." % specs['name'] self.assertErrorRegex(EasyBuildError, error_regexp, obtain_ec_for, specs, [self.ec_dir], None) # should find matching easyconfig file specs = {'name': 'foo', 'version': '1.2.3'} res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], False) self.assertEqual(res[1], os.path.join(self.ec_dir, fns[-1])) # should not pick between multiple available toolchain names name = "pi" ver = "3.12" suff = "mysuff" specs.update({ 'name': name, 'version': ver, 'versionsuffix': suff }) error_regexp = ".*No toolchain name specified, and more than one available: .*" self.assertErrorRegex(EasyBuildError, error_regexp, obtain_ec_for, specs, [self.ec_dir], None) # should be able to generate an easyconfig file that slightly differs ver = '3.16' specs.update({ 'toolchain_name': tcname, 'toolchain_version': tcver, 'version': ver, 'foo': 'bar123' }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[1], "%s-%s-%s-%s%s.eb" % (name, ver, tcname, tcver, suff)) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['name'], specs['name']) self.assertEqual(ec['version'], specs['version']) self.assertEqual(ec['versionsuffix'], specs['versionsuffix']) self.assertEqual(ec['toolchain'], {'name': tcname, 'version': tcver}) # can't check for key 'foo', because EasyConfig ignores parameter names it doesn't know about txt = read_file(res[1]) self.assertTrue(re.search('foo = "%s"' % specs['foo'], txt)) os.remove(res[1]) # should pick correct version, i.e. not newer than what's specified, if a choice needs to be made ver = '3.14' specs.update({'version': ver}) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['version'], specs['version']) txt = read_file(res[1]) self.assertTrue(re.search("version = [\"']%s[\"'] .*was: [\"']3.13[\"']" % ver, txt)) os.remove(res[1]) # should pick correct toolchain version as well, i.e. now newer than what's specified, if a choice needs to be made specs.update({ 'version': '3.15', 'toolchain_version': '4.4.5', }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['version'], specs['version']) self.assertEqual(ec['toolchain']['version'], specs['toolchain_version']) txt = read_file(res[1]) pattern = "toolchain = .*version.*[\"']%s[\"'].*was: .*version.*[\"']%s[\"']" % (specs['toolchain_version'], tcver) self.assertTrue(re.search(pattern, txt)) os.remove(res[1]) # should be able to prepend to list of patches and handle list of dependencies new_patches = ['two.patch', 'three.patch'] specs.update({ 'patches': new_patches[:], 'dependencies': [('foo', '1.2.3'), ('bar', '666', '-bleh', ('gompi', '1.4.10'))], }) parsed_deps = [ { 'name': 'foo', 'version': '1.2.3', 'versionsuffix': '', 'toolchain': ec['toolchain'], 'dummy': False, 'mod_name': 'foo/1.2.3-GCC-4.4.5', }, { 'name': 'bar', 'version': '666', 'versionsuffix': '-bleh', 'toolchain': {'name': 'gompi', 'version': '1.4.10'}, 'dummy': False, 'mod_name': 'bar/666-gompi-1.4.10-bleh', }, ] res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['patches'], specs['patches']) self.assertEqual(ec['dependencies'], parsed_deps) os.remove(res[1]) # verify append functionality for lists specs['patches'].insert(0, '') res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['patches'], patches + new_patches) specs['patches'].remove('') os.remove(res[1]) # verify prepend functionality for lists specs['patches'].append('') res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['patches'], new_patches + patches) os.remove(res[1]) # should use supplied filename fn = "my.eb" res = obtain_ec_for(specs, [self.ec_dir], fn) self.assertEqual(res[0], True) self.assertEqual(res[1], fn) os.remove(res[1]) # should use a template if it's there tpl_path = os.path.join("share", "easybuild", "easyconfigs", "TEMPLATE.eb") def trim_path(path): dirs = path.split(os.path.sep) if len(dirs) > 3 and 'site-packages' in dirs: if path.endswith('.egg'): path = os.path.join(*dirs[:-4]) # strip of lib/python2.7/site-packages/*.egg part else: path = os.path.join(*dirs[:-3]) # strip of lib/python2.7/site-packages part return path tpl_full_path = find_full_path(tpl_path, trim=trim_path) # only run this test if the TEMPLATE.eb file is available # TODO: use unittest.skip for this (but only works from Python 2.7) if tpl_full_path: shutil.copy2(tpl_full_path, self.ec_dir) specs.update({'name': 'nosuchsoftware'}) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['name'], specs['name']) os.remove(res[1]) # cleanup shutil.rmtree(self.ec_dir)
def xtest_resolve_dependencies(self): """ Test with some basic testcases (also check if he can find dependencies inside the given directory """ # replace Modules class with something we have control over config.modules_tool = mock_module ectools.modules_tool = mock_module robot.modules_tool = mock_module os.environ['module'] = "() { eval `/bin/echo $*`\n}" base_easyconfig_dir = find_full_path(os.path.join("test", "framework", "easyconfigs")) self.assertTrue(base_easyconfig_dir) easyconfig = { 'spec': '_', 'full_mod_name': 'name/version', 'short_mod_name': 'name/version', 'dependencies': [] } build_options = { 'allow_modules_tool_mismatch': True, 'robot_path': None, 'validate': False, } init_config(build_options=build_options) res = resolve_dependencies([deepcopy(easyconfig)]) self.assertEqual([easyconfig], res) easyconfig_dep = { 'ec': { 'name': 'foo', 'version': '1.2.3', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, }, 'spec': '_', 'short_mod_name': 'foo/1.2.3', 'full_mod_name': 'foo/1.2.3', 'dependencies': [{ 'name': 'gzip', 'version': '1.4', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': False, }], 'parsed': True, } build_options.update({'robot': True, 'robot_path': base_easyconfig_dir}) init_config(build_options=build_options) res = resolve_dependencies([deepcopy(easyconfig_dep)]) # dependency should be found, order should be correct self.assertEqual(len(res), 2) self.assertEqual('gzip/1.4', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) # hidden dependencies are found too, but only retained if they're not available (or forced to be retained hidden_dep = { 'name': 'toy', 'version': '0.0', 'versionsuffix': '-deps', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': True, } easyconfig_moredeps = deepcopy(easyconfig_dep) easyconfig_moredeps['dependencies'].append(hidden_dep) easyconfig_moredeps['hiddendependencies'] = [hidden_dep] # toy/.0.0-deps is available and thus should be omitted res = resolve_dependencies([deepcopy(easyconfig_moredeps)]) self.assertEqual(len(res), 2) full_mod_names = [ec['full_mod_name'] for ec in res] self.assertFalse('toy/.0.0-deps' in full_mod_names) res = resolve_dependencies([deepcopy(easyconfig_moredeps)], retain_all_deps=True) self.assertEqual(len(res), 4) # hidden dep toy/.0.0-deps (+1) depends on (fake) ictce/4.1.13 (+1) self.assertEqual('gzip/1.4', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) full_mod_names = [ec['full_mod_name'] for ec in res] self.assertTrue('toy/.0.0-deps' in full_mod_names) self.assertTrue('ictce/4.1.13' in full_mod_names) # here we have included a dependency in the easyconfig list easyconfig['full_mod_name'] = 'gzip/1.4' ecs = [deepcopy(easyconfig_dep), deepcopy(easyconfig)] build_options.update({'robot_path': None}) init_config(build_options=build_options) res = resolve_dependencies(ecs) # all dependencies should be resolved self.assertEqual(0, sum(len(ec['dependencies']) for ec in res)) # this should not resolve (cannot find gzip-1.4.eb), both with and without robot enabled ecs = [deepcopy(easyconfig_dep)] msg = "Irresolvable dependencies encountered" self.assertErrorRegex(EasyBuildError, msg, resolve_dependencies, ecs) # test if dependencies of an automatically found file are also loaded easyconfig_dep['dependencies'] = [{ 'name': 'gzip', 'version': '1.4', 'versionsuffix': '', 'toolchain': {'name': 'GCC', 'version': '4.6.3'}, 'dummy': True, 'hidden': False, }] ecs = [deepcopy(easyconfig_dep)] build_options.update({'robot_path': base_easyconfig_dir}) init_config(build_options=build_options) res = resolve_dependencies([deepcopy(easyconfig_dep)]) # GCC should be first (required by gzip dependency) self.assertEqual('GCC/4.6.3', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) # make sure that only missing stuff is built, and that available modules are not rebuilt # monkey patch MockModule to pretend that all ingredients required for goolf-1.4.10 toolchain are present MockModule.avail_modules = [ 'GCC/4.7.2', 'OpenMPI/1.6.4-GCC-4.7.2', 'OpenBLAS/0.2.6-gompi-1.4.10-LAPACK-3.4.2', 'FFTW/3.3.3-gompi-1.4.10', 'ScaLAPACK/2.0.2-gompi-1.4.10-OpenBLAS-0.2.6-LAPACK-3.4.2', ] easyconfig_dep['dependencies'] = [{ 'name': 'goolf', 'version': '1.4.10', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': False, }] ecs = [deepcopy(easyconfig_dep)] res = resolve_dependencies(ecs) # there should only be two retained builds, i.e. the software itself and the goolf toolchain as dep self.assertEqual(len(res), 2) # goolf should be first, the software itself second self.assertEqual('goolf/1.4.10', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[1]['full_mod_name']) # force doesn't trigger rebuild of all deps, but listed easyconfigs for which a module is available are rebuilt build_options.update({'force': True}) init_config(build_options=build_options) easyconfig['full_mod_name'] = 'this/is/already/there' MockModule.avail_modules.append('this/is/already/there') ecs = [deepcopy(easyconfig_dep), deepcopy(easyconfig)] res = resolve_dependencies(ecs) # there should only be three retained builds, foo + goolf dep and the additional build (even though a module is available) self.assertEqual(len(res), 3) # goolf should be first, the software itself second self.assertEqual('this/is/already/there', res[0]['full_mod_name']) self.assertEqual('goolf/1.4.10', res[1]['full_mod_name']) self.assertEqual('foo/1.2.3', res[2]['full_mod_name']) # build that are listed but already have a module available are not retained without force build_options.update({'force': False}) init_config(build_options=build_options) newecs = skip_available(ecs) # skip available builds since force is not enabled res = resolve_dependencies(newecs) self.assertEqual(len(res), 2) self.assertEqual('goolf/1.4.10', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[1]['full_mod_name']) # with retain_all_deps enabled, all dependencies ae retained build_options.update({'retain_all_deps': True}) init_config(build_options=build_options) ecs = [deepcopy(easyconfig_dep)] newecs = skip_available(ecs) # skip available builds since force is not enabled res = resolve_dependencies(newecs) self.assertEqual(len(res), 9) self.assertEqual('GCC/4.7.2', res[0]['full_mod_name']) self.assertEqual('goolf/1.4.10', res[-2]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) build_options.update({'retain_all_deps': False}) init_config(build_options=build_options) # provide even less goolf ingredients (no OpenBLAS/ScaLAPACK), make sure the numbers add up MockModule.avail_modules = [ 'GCC/4.7.2', 'OpenMPI/1.6.4-GCC-4.7.2', 'gompi/1.4.10', 'FFTW/3.3.3-gompi-1.4.10', ] easyconfig_dep['dependencies'] = [{ 'name': 'goolf', 'version': '1.4.10', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': False, }] ecs = [deepcopy(easyconfig_dep)] res = resolve_dependencies([deepcopy(easyconfig_dep)]) # there should only be two retained builds, i.e. the software itself and the goolf toolchain as dep self.assertEqual(len(res), 4) # goolf should be first, the software itself second self.assertEqual('OpenBLAS/0.2.6-gompi-1.4.10-LAPACK-3.4.2', res[0]['full_mod_name']) self.assertEqual('ScaLAPACK/2.0.2-gompi-1.4.10-OpenBLAS-0.2.6-LAPACK-3.4.2', res[1]['full_mod_name']) self.assertEqual('goolf/1.4.10', res[2]['full_mod_name']) self.assertEqual('foo/1.2.3', res[3]['full_mod_name']) config.modules_tool = ORIG_MODULES_TOOL ectools.modules_tool = ORIG_ECTOOLS_MODULES_TOOL robot.modules_tool = ORIG_ROBOT_MODULES_TOOL if ORIG_MODULE_FUNCTION is not None: os.environ['module'] = ORIG_MODULE_FUNCTION else: if 'module' in os.environ: del os.environ['module']
def setUp(self): """Setup for tests.""" # make sure path with modules for testing is added to MODULEPATH self.orig_modpath = os.environ.get('MODULEPATH', '') os.environ['MODULEPATH'] = find_full_path(os.path.join('test', 'framework', 'modules'))
def test_obtain_easyconfig(self): """test obtaining an easyconfig file given certain specifications""" tcname = 'GCC' tcver = '4.3.2' patches = ["one.patch"] # prepare a couple of eb files to test again fns = ["pi-3.14.eb", "pi-3.13-GCC-4.3.2.eb", "pi-3.15-GCC-4.3.2.eb", "pi-3.15-GCC-4.4.5.eb", "foo-1.2.3-GCC-4.3.2.eb"] eb_files = [(fns[0], "\n".join([ 'easyblock = "ConfigureMake"', 'name = "pi"', 'version = "3.12"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "dummy", "version": "dummy"}', 'patches = %s' % patches ])), (fns[1], "\n".join([ 'easyblock = "ConfigureMake"', 'name = "pi"', 'version = "3.13"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'patches = %s' % patches ])), (fns[2], "\n".join([ 'easyblock = "ConfigureMake"', 'name = "pi"', 'version = "3.15"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'patches = %s' % patches ])), (fns[3], "\n".join([ 'easyblock = "ConfigureMake"', 'name = "pi"', 'version = "3.15"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "4.5.1"}' % tcname, 'patches = %s' % patches ])), (fns[4], "\n".join([ 'easyblock = "ConfigureMake"', 'name = "foo"', 'version = "1.2.3"', 'homepage = "http://example.com"', 'description = "test easyconfig"', 'toolchain = {"name": "%s", "version": "%s"}' % (tcname, tcver), 'foo_extra1 = "bar"', ])) ] self.ec_dir = tempfile.mkdtemp() for (fn, txt) in eb_files: write_file(os.path.join(self.ec_dir, fn), txt) # should crash when no suited easyconfig file (or template) is available specs = {'name': 'nosuchsoftware'} error_regexp = ".*No easyconfig files found for software %s, and no templates available. I'm all out of ideas." % specs['name'] self.assertErrorRegex(EasyBuildError, error_regexp, obtain_ec_for, specs, [self.ec_dir], None) # should find matching easyconfig file specs = { 'name': 'foo', 'version': '1.2.3' } res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], False) self.assertEqual(res[1], os.path.join(self.ec_dir, fns[-1])) # should not pick between multiple available toolchain names name = "pi" ver = "3.12" suff = "mysuff" specs.update({ 'name': name, 'version': ver, 'versionsuffix': suff }) error_regexp = ".*No toolchain name specified, and more than one available: .*" self.assertErrorRegex(EasyBuildError, error_regexp, obtain_ec_for, specs, [self.ec_dir], None) # should be able to generate an easyconfig file that slightly differs ver = '3.16' specs.update({ 'toolchain_name': tcname, 'toolchain_version': tcver, 'version': ver, 'start_dir': 'bar123' }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[1], "%s-%s-%s-%s%s.eb" % (name, ver, tcname, tcver, suff)) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['name'], specs['name']) self.assertEqual(ec['version'], specs['version']) self.assertEqual(ec['versionsuffix'], specs['versionsuffix']) self.assertEqual(ec['toolchain'], {'name': tcname, 'version': tcver}) self.assertEqual(ec['start_dir'], specs['start_dir']) os.remove(res[1]) specs.update({ 'foo': 'bar123' }) self.assertErrorRegex(EasyBuildError, "Unkown easyconfig parameter: foo", obtain_ec_for, specs, [self.ec_dir], None) del specs['foo'] # should pick correct version, i.e. not newer than what's specified, if a choice needs to be made ver = '3.14' specs.update({'version': ver}) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['version'], specs['version']) txt = read_file(res[1]) self.assertTrue(re.search("^version = [\"']%s[\"']$" % ver, txt, re.M)) os.remove(res[1]) # should pick correct toolchain version as well, i.e. now newer than what's specified, if a choice needs to be made specs.update({ 'version': '3.15', 'toolchain_version': '4.4.5', }) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['version'], specs['version']) self.assertEqual(ec['toolchain']['version'], specs['toolchain_version']) txt = read_file(res[1]) pattern = "^toolchain = .*version.*[\"']%s[\"'].*}$" % specs['toolchain_version'] self.assertTrue(re.search(pattern, txt, re.M)) os.remove(res[1]) # should be able to prepend to list of patches and handle list of dependencies new_patches = ['two.patch', 'three.patch'] specs.update({ 'patches': new_patches[:], 'dependencies': [('foo', '1.2.3'), ('bar', '666', '-bleh', ('gompi', '1.4.10'))], 'hiddendependencies': [('test', '3.2.1')], }) parsed_deps = [ { 'name': 'foo', 'version': '1.2.3', 'versionsuffix': '', 'toolchain': ec['toolchain'], 'dummy': False, 'short_mod_name': 'foo/1.2.3-GCC-4.4.5', 'full_mod_name': 'foo/1.2.3-GCC-4.4.5', 'hidden': False, 'external_module': False, 'external_module_metadata': {}, }, { 'name': 'bar', 'version': '666', 'versionsuffix': '-bleh', 'toolchain': {'name': 'gompi', 'version': '1.4.10'}, 'dummy': False, 'short_mod_name': 'bar/666-gompi-1.4.10-bleh', 'full_mod_name': 'bar/666-gompi-1.4.10-bleh', 'hidden': False, 'external_module': False, 'external_module_metadata': {}, }, { 'name': 'test', 'version': '3.2.1', 'versionsuffix': '', 'toolchain': ec['toolchain'], 'dummy': False, 'short_mod_name': 'test/.3.2.1-GCC-4.4.5', 'full_mod_name': 'test/.3.2.1-GCC-4.4.5', 'hidden': True, 'external_module': False, 'external_module_metadata': {}, }, ] # hidden dependencies must be included in list of dependencies res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) error_pattern = "Hidden dependencies with visible module names .* not in list of dependencies: .*" self.assertErrorRegex(EasyBuildError, error_pattern, EasyConfig, res[1]) specs['dependencies'].append(('test', '3.2.1')) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['patches'], specs['patches']) self.assertEqual(ec.dependencies(), parsed_deps) # hidden dependencies are filtered from list of dependencies self.assertFalse('test/3.2.1-GCC-4.4.5' in [d['full_mod_name'] for d in ec['dependencies']]) self.assertTrue('test/.3.2.1-GCC-4.4.5' in [d['full_mod_name'] for d in ec['hiddendependencies']]) os.remove(res[1]) # hidden dependencies are also filtered from list of dependencies when validation is skipped res = obtain_ec_for(specs, [self.ec_dir], None) ec = EasyConfig(res[1], validate=False) self.assertFalse('test/3.2.1-GCC-4.4.5' in [d['full_mod_name'] for d in ec['dependencies']]) self.assertTrue('test/.3.2.1-GCC-4.4.5' in [d['full_mod_name'] for d in ec['hiddendependencies']]) os.remove(res[1]) # verify append functionality for lists specs['patches'].insert(0, '') res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['patches'], patches + new_patches) specs['patches'].remove('') os.remove(res[1]) # verify prepend functionality for lists specs['patches'].append('') res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['patches'], new_patches + patches) os.remove(res[1]) # should use supplied filename fn = "my.eb" res = obtain_ec_for(specs, [self.ec_dir], fn) self.assertEqual(res[0], True) self.assertEqual(res[1], fn) os.remove(res[1]) # should use a template if it's there tpl_path = os.path.join("share", "easybuild", "easyconfigs", "TEMPLATE.eb") def trim_path(path): dirs = path.split(os.path.sep) if len(dirs) > 3 and 'site-packages' in dirs: if path.endswith('.egg'): path = os.path.join(*dirs[:-4]) # strip of lib/python2.7/site-packages/*.egg part else: path = os.path.join(*dirs[:-3]) # strip of lib/python2.7/site-packages part return path tpl_full_path = find_full_path(tpl_path, trim=trim_path) # only run this test if the TEMPLATE.eb file is available # TODO: use unittest.skip for this (but only works from Python 2.7) if tpl_full_path: shutil.copy2(tpl_full_path, self.ec_dir) specs.update({'name': 'nosuchsoftware'}) res = obtain_ec_for(specs, [self.ec_dir], None) self.assertEqual(res[0], True) ec = EasyConfig(res[1]) self.assertEqual(ec['name'], specs['name']) os.remove(res[1]) # cleanup shutil.rmtree(self.ec_dir)
def legacySetUp(self): self.log.deprecated("legacySetUp", "2.0") cfg_path = os.path.join('easybuild', 'easybuild_config.py') cfg_full_path = find_full_path(cfg_path) self.assertTrue(cfg_full_path)
def test_resolve_dependencies(self): """ Test with some basic testcases (also check if he can find dependencies inside the given directory """ self.install_mock_module() base_easyconfig_dir = find_full_path(os.path.join('test', 'framework', 'easyconfigs', 'test_ecs')) self.assertTrue(base_easyconfig_dir) easyconfig = { 'spec': '_', 'full_mod_name': 'name/version', 'short_mod_name': 'name/version', 'dependencies': [] } build_options = { 'allow_modules_tool_mismatch': True, 'external_modules_metadata': ConfigObj(), 'robot_path': None, 'validate': False, } init_config(build_options=build_options) res = resolve_dependencies([deepcopy(easyconfig)], self.modtool) self.assertEqual([easyconfig], res) easyconfig_dep = { 'ec': { 'name': 'foo', 'version': '1.2.3', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, }, 'spec': '_', 'short_mod_name': 'foo/1.2.3', 'full_mod_name': 'foo/1.2.3', 'dependencies': [{ 'name': 'gzip', 'version': '1.4', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': False, }], 'parsed': True, } build_options.update({'robot': True, 'robot_path': base_easyconfig_dir}) init_config(build_options=build_options) res = resolve_dependencies([deepcopy(easyconfig_dep)], self.modtool) # dependency should be found, order should be correct self.assertEqual(len(res), 2) self.assertEqual('gzip/1.4', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) # hidden dependencies are found too, but only retained if they're not available (or forced to be retained hidden_dep = { 'name': 'toy', 'version': '0.0', 'versionsuffix': '-deps', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': True, } easyconfig_moredeps = deepcopy(easyconfig_dep) easyconfig_moredeps['dependencies'].append(hidden_dep) easyconfig_moredeps['hiddendependencies'] = [hidden_dep] # toy/.0.0-deps is available and thus should be omitted res = resolve_dependencies([deepcopy(easyconfig_moredeps)], self.modtool) self.assertEqual(len(res), 2) full_mod_names = [ec['full_mod_name'] for ec in res] self.assertFalse('toy/.0.0-deps' in full_mod_names) res = resolve_dependencies([deepcopy(easyconfig_moredeps)], self.modtool, retain_all_deps=True) self.assertEqual(len(res), 4) # hidden dep toy/.0.0-deps (+1) depends on (fake) ictce/4.1.13 (+1) self.assertEqual('gzip/1.4', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) full_mod_names = [ec['full_mod_name'] for ec in res] self.assertTrue('toy/.0.0-deps' in full_mod_names) self.assertTrue('ictce/4.1.13' in full_mod_names) # here we have included a dependency in the easyconfig list easyconfig['full_mod_name'] = 'gzip/1.4' ecs = [deepcopy(easyconfig_dep), deepcopy(easyconfig)] build_options.update({'robot_path': None}) init_config(build_options=build_options) res = resolve_dependencies(ecs, self.modtool) # all dependencies should be resolved self.assertEqual(0, sum(len(ec['dependencies']) for ec in res)) # this should not resolve (cannot find gzip-1.4.eb), both with and without robot enabled ecs = [deepcopy(easyconfig_dep)] msg = "Irresolvable dependencies encountered" self.assertErrorRegex(EasyBuildError, msg, resolve_dependencies, ecs, self.modtool) # test if dependencies of an automatically found file are also loaded easyconfig_dep['dependencies'] = [{ 'name': 'gzip', 'version': '1.4', 'versionsuffix': '', 'toolchain': {'name': 'GCC', 'version': '4.6.3'}, 'dummy': True, 'hidden': False, }] ecs = [deepcopy(easyconfig_dep)] build_options.update({'robot_path': base_easyconfig_dir}) init_config(build_options=build_options) res = resolve_dependencies([deepcopy(easyconfig_dep)], self.modtool) # GCC should be first (required by gzip dependency) self.assertEqual('GCC/4.6.3', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) # make sure that only missing stuff is built, and that available modules are not rebuilt # monkey patch MockModule to pretend that all ingredients required for goolf-1.4.10 toolchain are present MockModule.avail_modules = [ 'GCC/4.7.2', 'OpenMPI/1.6.4-GCC-4.7.2', 'OpenBLAS/0.2.6-gompi-1.4.10-LAPACK-3.4.2', 'FFTW/3.3.3-gompi-1.4.10', 'ScaLAPACK/2.0.2-gompi-1.4.10-OpenBLAS-0.2.6-LAPACK-3.4.2', ] easyconfig_dep['dependencies'] = [{ 'name': 'goolf', 'version': '1.4.10', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': False, }] ecs = [deepcopy(easyconfig_dep)] res = resolve_dependencies(ecs, self.modtool) # there should only be two retained builds, i.e. the software itself and the goolf toolchain as dep self.assertEqual(len(res), 2) # goolf should be first, the software itself second self.assertEqual('goolf/1.4.10', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[1]['full_mod_name']) # force doesn't trigger rebuild of all deps, but listed easyconfigs for which a module is available are rebuilt build_options.update({'force': True}) init_config(build_options=build_options) easyconfig['full_mod_name'] = 'this/is/already/there' MockModule.avail_modules.append('this/is/already/there') ecs = [deepcopy(easyconfig_dep), deepcopy(easyconfig)] res = resolve_dependencies(ecs, self.modtool) # there should only be three retained builds, foo + goolf dep and the additional build (even though a module is available) self.assertEqual(len(res), 3) # goolf should be first, the software itself second self.assertEqual('this/is/already/there', res[0]['full_mod_name']) self.assertEqual('goolf/1.4.10', res[1]['full_mod_name']) self.assertEqual('foo/1.2.3', res[2]['full_mod_name']) # build that are listed but already have a module available are not retained without force build_options.update({'force': False}) init_config(build_options=build_options) newecs = skip_available(ecs, self.modtool) # skip available builds since force is not enabled res = resolve_dependencies(newecs, self.modtool) self.assertEqual(len(res), 2) self.assertEqual('goolf/1.4.10', res[0]['full_mod_name']) self.assertEqual('foo/1.2.3', res[1]['full_mod_name']) # with retain_all_deps enabled, all dependencies ae retained build_options.update({'retain_all_deps': True}) init_config(build_options=build_options) ecs = [deepcopy(easyconfig_dep)] newecs = skip_available(ecs, self.modtool) # skip available builds since force is not enabled res = resolve_dependencies(newecs, self.modtool) self.assertEqual(len(res), 9) self.assertEqual('GCC/4.7.2', res[0]['full_mod_name']) self.assertEqual('goolf/1.4.10', res[-2]['full_mod_name']) self.assertEqual('foo/1.2.3', res[-1]['full_mod_name']) build_options.update({'retain_all_deps': False}) init_config(build_options=build_options) # provide even less goolf ingredients (no OpenBLAS/ScaLAPACK), make sure the numbers add up MockModule.avail_modules = [ 'GCC/4.7.2', 'OpenMPI/1.6.4-GCC-4.7.2', 'gompi/1.4.10', 'FFTW/3.3.3-gompi-1.4.10', ] easyconfig_dep['dependencies'] = [{ 'name': 'goolf', 'version': '1.4.10', 'versionsuffix': '', 'toolchain': {'name': 'dummy', 'version': 'dummy'}, 'dummy': True, 'hidden': False, }] ecs = [deepcopy(easyconfig_dep)] res = resolve_dependencies([deepcopy(easyconfig_dep)], self.modtool) # there should only be two retained builds, i.e. the software itself and the goolf toolchain as dep self.assertEqual(len(res), 4) # goolf should be first, the software itself second self.assertEqual('OpenBLAS/0.2.6-gompi-1.4.10-LAPACK-3.4.2', res[0]['full_mod_name']) self.assertEqual('ScaLAPACK/2.0.2-gompi-1.4.10-OpenBLAS-0.2.6-LAPACK-3.4.2', res[1]['full_mod_name']) self.assertEqual('goolf/1.4.10', res[2]['full_mod_name']) self.assertEqual('foo/1.2.3', res[3]['full_mod_name'])