def test_external_and_virtual(self): spec = Spec('externaltest') spec.concretize() self.assertEqual(spec['externaltool'].external, '/path/to/external_tool') self.assertEqual(spec['stuff'].external, '/path/to/external_virtual_gcc') self.assertTrue(spec['externaltool'].compiler.satisfies('gcc')) self.assertTrue(spec['stuff'].compiler.satisfies('gcc'))
def test_with_or_without(self): s = Spec('a') s.concretize() pkg = spack.repo.get(s) # Called without parameters options = pkg.with_or_without('foo') assert '--with-bar' in options assert '--without-baz' in options assert '--no-fee' in options def activate(value): return 'something' options = pkg.with_or_without('foo', activation_value=activate) assert '--with-bar=something' in options assert '--without-baz' in options assert '--no-fee' in options options = pkg.enable_or_disable('foo') assert '--enable-bar' in options assert '--disable-baz' in options assert '--disable-fee' in options options = pkg.with_or_without('bvv') assert '--with-bvv' in options
def test_yaml_subdag(config, builtin_mock): spec = Spec('mpileaks^mpich+debug') spec.concretize() yaml_spec = Spec.from_yaml(spec.to_yaml()) for dep in ('callpath', 'mpich', 'dyninst', 'libdwarf', 'libelf'): assert spec[dep].eq_dag(yaml_spec[dep])
def test_conditional_patched_deps_with_conditions(mock_packages, config): """Test whether conditional patched dependencies with conditions work.""" spec = Spec('patch-several-dependencies @1.0 ^libdwarf@20111030') spec.concretize() # basic patch on libelf assert 'patches' in list(spec['libelf'].variants.keys()) # foo assert ('b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c' in spec['libelf'].variants['patches'].value) # conditional patch on libdwarf assert 'patches' in list(spec['libdwarf'].variants.keys()) # bar assert ('7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730' in spec['libdwarf'].variants['patches'].value) # baz is conditional on libdwarf version (no guarantee on order w/conds) assert ('bf07a7fbb825fc0aae7bf4a1177b2b31fcf8a3feeaf7092761e18c859ee52a9c' in spec['libdwarf'].variants['patches'].value) # URL patches assert 'patches' in list(spec['fake'].variants.keys()) # urlpatch.patch, urlpatch.patch.gz assert (('1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd', 'abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234') == spec['fake'].variants['patches'].value)
def test_getitem_query(self): s = Spec('mpileaks') s.concretize() # Check a query to a non-virtual package a = s['callpath'] query = a.last_query assert query.name == 'callpath' assert len(query.extra_parameters) == 0 assert not query.isvirtual # Check a query to a virtual package a = s['mpi'] query = a.last_query assert query.name == 'mpi' assert len(query.extra_parameters) == 0 assert query.isvirtual # Check a query to a virtual package with # extra parameters after query a = s['mpi:cxx,fortran'] query = a.last_query assert query.name == 'mpi' assert len(query.extra_parameters) == 2 assert 'cxx' in query.extra_parameters assert 'fortran' in query.extra_parameters assert query.isvirtual
def test_install_overwrite( mock_packages, mock_archive, mock_fetch, config, install_mockery ): # It's not possible to overwrite something that is not yet installed with pytest.raises(AssertionError): install('--overwrite', 'libdwarf') # --overwrite requires a single spec with pytest.raises(AssertionError): install('--overwrite', 'libdwarf', 'libelf') # Try to install a spec and then to reinstall it. spec = Spec('libdwarf') spec.concretize() install('libdwarf') assert os.path.exists(spec.prefix) expected_md5 = fs.hash_directory(spec.prefix) # Modify the first installation to be sure the content is not the same # as the one after we reinstalled with open(os.path.join(spec.prefix, 'only_in_old'), 'w') as f: f.write('This content is here to differentiate installations.') bad_md5 = fs.hash_directory(spec.prefix) assert bad_md5 != expected_md5 install('--overwrite', '-y', 'libdwarf') assert os.path.exists(spec.prefix) assert fs.hash_directory(spec.prefix) == expected_md5 assert fs.hash_directory(spec.prefix) != bad_md5
def test_patched_dependency( mock_packages, config, install_mockery, mock_fetch): """Test whether patched dependencies work.""" spec = Spec('patch-a-dependency') spec.concretize() assert 'patches' in list(spec['libelf'].variants.keys()) # make sure the patch makes it into the dependency spec assert (('c45c1564f70def3fc1a6e22139f62cb21cd190cc3a7dbe6f4120fa59ce33dcb8',) == spec['libelf'].variants['patches'].value) # make sure the patch in the dependent's directory is applied to the # dependency libelf = spec['libelf'] pkg = libelf.package pkg.do_patch() with pkg.stage: with working_dir(pkg.stage.source_path): # output a Makefile with 'echo Patched!' as the default target configure = Executable('./configure') configure() # Make sure the Makefile contains the patched text with open('Makefile') as mf: assert 'Patched!' in mf.read()
def test_external_and_virtual(self): spec = Spec('externaltest') spec.concretize() assert spec['externaltool'].external_path == '/path/to/external_tool' assert spec['stuff'].external_path == '/path/to/external_virtual_gcc' assert spec['externaltool'].compiler.satisfies('gcc') assert spec['stuff'].compiler.satisfies('gcc')
def test_copy_satisfies_transitive(self): spec = Spec('dttop') spec.concretize() copy = spec.copy() for s in spec.traverse(): assert s.satisfies(copy[s.name]) assert copy[s.name].satisfies(s)
def test_conflicts_in_spec(self, conflict_spec): # Check that an exception is raised an caught by the appropriate # exception types. for exc_type in (ConflictsInSpecError, RuntimeError, SpecError): s = Spec(conflict_spec) with pytest.raises(exc_type): s.concretize()
def test_regression_issue_7705(self): # spec.package.provides(name) doesn't account for conditional # constraints in the concretized spec s = Spec('simple-inheritance~openblas') s.concretize() assert not s.package.provides('lapack')
def test_test_deptype(): """Ensure that test-only dependencies are only included for specified packages in the following spec DAG:: w /| x y | z w->y deptypes are (link, build), w->x and y->z deptypes are (test) """ default = ('build', 'link') test_only = ('test',) x = MockPackage('x', [], []) z = MockPackage('z', [], []) y = MockPackage('y', [z], [test_only]) w = MockPackage('w', [x, y], [test_only, default]) mock_repo = MockPackageMultiRepo([w, x, y, z]) with spack.repo.swap(mock_repo): spec = Spec('w') spec.concretize(tests=(w.name,)) assert ('x' in spec) assert ('z' not in spec)
def test_external_package(self): spec = Spec('externaltool') spec.concretize() self.assertEqual(spec['externaltool'].external, '/path/to/external_tool') self.assertFalse('externalprereq' in spec) self.assertTrue(spec['externaltool'].compiler.satisfies('gcc'))
def test_my_dep_depends_on_provider_of_my_virtual_dep(self): spec = Spec('indirect_mpich') spec.normalize() print print spec.tree(color=True) spec.concretize()
def test_external_spec(config, mock_packages): spec = Spec('externaltool') spec.concretize() check_yaml_round_trip(spec) spec = Spec('externaltest') spec.concretize() check_yaml_round_trip(spec)
def test_external_spec(config, builtin_mock): spec = Spec('externaltool') spec.concretize() check_yaml_round_trip(spec) spec = Spec('externaltest') spec.concretize() check_yaml_round_trip(spec)
def test_architecture_inheritance(self): """test_architecture_inheritance is likely to fail with an UnavailableCompilerVersionError if the architecture is concretized incorrectly. """ spec = Spec('cmake-client %[email protected] os=fe ^ cmake') spec.concretize() assert spec['cmake'].architecture == spec.architecture
def test_unsatisfied_single_valued_variant(self): a = Spec('a foobar=baz') a.concretize() assert '^b' not in a mv = Spec('multivalue_variant') mv.concretize() assert '[email protected]' not in mv
def test_compiler_inheritance(self): spec = Spec('mpileaks') spec.normalize() spec['dyninst'].compiler = CompilerSpec('clang') spec.concretize() # TODO: not exactly the syntax I would like. assert spec['libdwarf'].compiler.satisfies('clang') assert spec['libelf'].compiler.satisfies('clang')
def test_nobuild_package(self): got_error = False spec = Spec('externaltool%clang') try: spec.concretize() except spack.concretize.NoBuildError: got_error = True self.assertTrue(got_error)
def test_yaml_subdag(self): spec = Spec('mpileaks^mpich+debug') spec.concretize() yaml_spec = Spec.from_yaml(spec.to_yaml()) for dep in ('callpath', 'mpich', 'dyninst', 'libdwarf', 'libelf'): self.assertTrue(spec[dep].eq_dag(yaml_spec[dep]))
def test_different_compilers_get_different_flags(self): client = Spec('cmake-client %[email protected] platform=test os=fe target=fe' + ' ^cmake %[email protected] platform=test os=fe target=fe') client.concretize() cmake = client['cmake'] assert set(client.compiler_flags['cflags']) == set(['-O0']) assert set(cmake.compiler_flags['cflags']) == set(['-O3']) assert set(client.compiler_flags['fflags']) == set(['-O0']) assert not set(cmake.compiler_flags['fflags'])
def test_compiler_inheritance(self): spec = Spec("mpileaks") spec.normalize() spec["dyninst"].compiler = CompilerSpec("clang") spec.concretize() # TODO: not exactly the syntax I would like. self.assertTrue(spec["libdwarf"].compiler.satisfies("clang")) self.assertTrue(spec["libelf"].compiler.satisfies("clang"))
def test_user_defaults(config): platform = spack.architecture.platform() default_os = str(platform.operating_system("default_os")) default_target = str(platform.target("default_target")) default_spec = Spec("libelf") # default is no args default_spec.concretize() assert default_os == default_spec.architecture.platform_os assert default_target == default_spec.architecture.target
def test_concretize_two_virtuals_with_dual_provider_and_a_conflict( self ): """Test a package with multiple virtual dependencies and force a provider that provides both, and another conflicting package that provides one. """ s = Spec('hypre ^openblas-with-lapack ^netlib-lapack') with pytest.raises(spack.spec.MultipleProviderError): s.concretize()
def test_virtual_is_fully_expanded_for_callpath(self): # force dependence on fake "zmpi" by asking for MPI 10.0 spec = Spec("callpath ^[email protected]") self.assertIn("mpi", spec.dependencies) self.assertNotIn("fake", spec) spec.concretize() self.assertIn("zmpi", spec.dependencies) self.assertNotIn("mpi", spec) self.assertIn("fake", spec.dependencies["zmpi"])
def test_installed_dependency_request_conflicts( install_mockery, mock_fetch, mutable_mock_packages): dependency = Spec('dependency-install') dependency.concretize() dependency.package.do_install() dependency_hash = dependency.dag_hash() dependent = Spec( 'conflicting-dependent ^/' + dependency_hash) with pytest.raises(spack.spec.UnsatisfiableSpecError): dependent.concretize()
def test_virtual_is_fully_expanded_for_callpath(self): # force dependence on fake "zmpi" by asking for MPI 10.0 spec = Spec('callpath ^[email protected]') assert 'mpi' in spec._dependencies assert 'fake' not in spec spec.concretize() assert 'zmpi' in spec._dependencies assert all('mpi' not in d._dependencies for d in spec.traverse()) assert 'zmpi' in spec assert 'mpi' in spec assert 'fake' in spec._dependencies['zmpi'].spec
def test_regression_issue_7941(self): # The string representation of a spec containing # an explicit multi-valued variant and a dependency # might be parsed differently than the originating spec s = Spec('a foobar=bar ^b') t = Spec(str(s)) s.concretize() t.concretize() assert s.dag_hash() == t.dag_hash()
def test_all_same_but_archive_hash(self): spec1 = Spec("[email protected]") spec2 = Spec("[email protected]") spec1.concretize() spec2.concretize() content1 = package_content(spec1) content1 = content1.replace(spec1.package.__class__.__name__, '') content2 = package_content(spec2) content2 = content2.replace(spec2.package.__class__.__name__, '') assert spec1.package.content_hash(content=content1) != \ spec2.package.content_hash(content=content2)
def test_concretize_deptypes(self): """Ensure that dependency types are preserved after concretization.""" s = Spec('dt-diamond') s.concretize() self.check_diamond_deptypes(s)
def test_default_rpaths_create_install_default_layout(tmpdir, mirror_directory_def, install_mockery): """ Test the creation and installation of buildcaches with default rpaths into the default directory layout scheme. """ gspec = Spec('garply') gspec.concretize() cspec = Spec('corge') cspec.concretize() iparser = argparse.ArgumentParser() install.setup_parser(iparser) # Install some packages with dependent packages iargs = iparser.parse_args(['--no-cache', cspec.name]) install.install(iparser, iargs) global mirror_path_def mirror_path_def = mirror_directory_def mparser = argparse.ArgumentParser() mirror.setup_parser(mparser) margs = mparser.parse_args( ['add', '--scope', 'site', 'test-mirror-def', 'file://%s' % mirror_path_def]) mirror.mirror(mparser, margs) margs = mparser.parse_args(['list']) mirror.mirror(mparser, margs) # setup argument parser parser = argparse.ArgumentParser() buildcache.setup_parser(parser) # Set default buildcache args create_args = ['create', '-a', '-u', '-d', str(mirror_path_def), cspec.name] install_args = ['install', '-a', '-u', cspec.name] # Create a buildache args = parser.parse_args(create_args) buildcache.buildcache(parser, args) # Test force overwrite create buildcache create_args.insert(create_args.index('-a'), '-f') args = parser.parse_args(create_args) buildcache.buildcache(parser, args) # create mirror index args = parser.parse_args(['update-index', '-d', 'file://%s' % str(mirror_path_def)]) buildcache.buildcache(parser, args) # list the buildcaches in the mirror args = parser.parse_args(['list', '-a', '-l', '-v']) buildcache.buildcache(parser, args) # Uninstall the package and deps uparser = argparse.ArgumentParser() uninstall.setup_parser(uparser) uargs = uparser.parse_args(['-y', '--dependents', gspec.name]) uninstall.uninstall(uparser, uargs) # test install args = parser.parse_args(install_args) buildcache.buildcache(parser, args) # This gives warning that spec is already installed buildcache.buildcache(parser, args) # test overwrite install install_args.insert(install_args.index('-a'), '-f') args = parser.parse_args(install_args) buildcache.buildcache(parser, args) args = parser.parse_args(['keys', '-f']) buildcache.buildcache(parser, args) args = parser.parse_args(['list']) buildcache.buildcache(parser, args) args = parser.parse_args(['list', '-a']) buildcache.buildcache(parser, args) args = parser.parse_args(['list', '-l', '-v']) buildcache.buildcache(parser, args) bindist._cached_specs = set() spack.stage.purge() margs = mparser.parse_args( ['rm', '--scope', 'site', 'test-mirror-def']) mirror.mirror(mparser, margs)
def test_ordered_read_not_required_for_consistent_dag_hash( config, builtin_mock): """Make sure ordered serialization isn't required to preserve hashes. For consistent hashes, we require that YAML and json documents have their keys serialized in a deterministic order. However, we don't want to require them to be serialized in order. This ensures that is not required. """ specs = ['mpileaks ^zmpi', 'dttop', 'dtuse'] for spec in specs: spec = Spec(spec) spec.concretize() # # Dict & corresponding YAML & JSON from the original spec. # spec_dict = spec.to_dict() spec_yaml = spec.to_yaml() spec_json = spec.to_json() # # Make a spec with reversed OrderedDicts for every # OrderedDict in the original. # reversed_spec_dict = reverse_all_dicts(spec.to_dict()) # # Dump to YAML and JSON # yaml_string = syaml.dump(spec_dict, default_flow_style=False) reversed_yaml_string = syaml.dump(reversed_spec_dict, default_flow_style=False) json_string = sjson.dump(spec_dict) reversed_json_string = sjson.dump(reversed_spec_dict) # # Do many consistency checks # # spec yaml is ordered like the spec dict assert yaml_string == spec_yaml assert json_string == spec_json # reversed string is different from the original, so it # *would* generate a different hash assert yaml_string != reversed_yaml_string assert json_string != reversed_json_string # build specs from the "wrongly" ordered data round_trip_yaml_spec = Spec.from_yaml(yaml_string) round_trip_json_spec = Spec.from_json(json_string) round_trip_reversed_yaml_spec = Spec.from_yaml(reversed_yaml_string) round_trip_reversed_json_spec = Spec.from_yaml(reversed_json_string) # TODO: remove this when build deps are in provenance. spec = spec.copy(deps=('link', 'run')) # specs are equal to the original assert spec == round_trip_yaml_spec assert spec == round_trip_json_spec assert spec == round_trip_reversed_yaml_spec assert spec == round_trip_reversed_json_spec assert round_trip_yaml_spec == round_trip_reversed_yaml_spec assert round_trip_json_spec == round_trip_reversed_json_spec # dag_hashes are equal assert spec.dag_hash() == round_trip_yaml_spec.dag_hash() assert spec.dag_hash() == round_trip_json_spec.dag_hash() assert spec.dag_hash() == round_trip_reversed_yaml_spec.dag_hash() assert spec.dag_hash() == round_trip_reversed_json_spec.dag_hash()
def concretize_multi_provider(self): s = Spec('mpileaks ^[email protected]') s.concretize() assert s['mpi'].version == ver('1.10.3')
def test_install_env_variables(mock_packages, mock_archive, mock_fetch, config, install_mockery): spec = Spec('libdwarf') spec.concretize() install('libdwarf') assert os.path.isfile(spec.package.install_env_path)
def test_update_sbang(tmpdir, test_mirror): """Test the creation and installation of buildcaches with default rpaths into the non-default directory layout scheme, triggering an update of the sbang. """ scheme = os.path.join( '${name}', '${version}', '${architecture}-${compiler.name}-${compiler.version}-${hash}') spec_str = 'old-sbang' # Concretize a package with some old-fashioned sbang lines. old_spec = Spec(spec_str).concretized() old_spec_hash_str = '/{0}'.format(old_spec.dag_hash()) # Need a fake mirror with *function* scope. mirror_dir = test_mirror mirror_url = 'file://{0}'.format(mirror_dir) # Assume all commands will concretize old_spec the same way. install_cmd('--no-cache', old_spec.name) # Create a buildcache with the installed spec. buildcache_cmd('create', '-u', '-a', '-d', mirror_dir, old_spec_hash_str) # Need to force an update of the buildcache index buildcache_cmd('update-index', '-d', mirror_url) # Uninstall the original package. uninstall_cmd('-y', old_spec_hash_str) # Switch the store to the new install tree locations newtree_dir = tmpdir.join('newtree') s = spack.store.Store(str(newtree_dir)) s.layout = YamlDirectoryLayout(str(newtree_dir), path_scheme=scheme) with spack.store.use_store(s): new_spec = Spec('old-sbang') new_spec.concretize() assert new_spec.dag_hash() == old_spec.dag_hash() # Install package from buildcache buildcache_cmd('install', '-a', '-u', '-f', new_spec.name) # Continue blowing away caches bindist.clear_spec_cache() spack.stage.purge() # test that the sbang was updated by the move sbang_style_1_expected = '''{0} #!/usr/bin/env python {1} '''.format(sbang.sbang_shebang_line(), new_spec.prefix.bin) sbang_style_2_expected = '''{0} #!/usr/bin/env python {1} '''.format(sbang.sbang_shebang_line(), new_spec.prefix.bin) installed_script_style_1_path = new_spec.prefix.bin.join( 'sbang-style-1.sh') assert sbang_style_1_expected == \ open(str(installed_script_style_1_path)).read() installed_script_style_2_path = new_spec.prefix.bin.join( 'sbang-style-2.sh') assert sbang_style_2_expected == \ open(str(installed_script_style_2_path)).read() uninstall_cmd('-y', '/%s' % new_spec.dag_hash())
def test_cmake_secondary_generator(config, mock_packages): s = Spec('cmake-client') s.concretize() pkg = spack.repo.get(s) pkg.generator = 'CodeBlocks - Unix Makefiles' assert get_std_cmake_args(pkg)
def test_my_dep_depends_on_provider_of_my_virtual_dep(self): spec = Spec('indirect-mpich') spec.normalize() spec.concretize()
def test_external_package(self): spec = Spec('externaltool%gcc') spec.concretize() assert spec['externaltool'].external_path == '/path/to/external_tool' assert 'externalprereq' not in spec assert spec['externaltool'].compiler.satisfies('gcc')
def test_no_compilers_for_arch(self): s = Spec('a arch=linux-rhel0-x86_64') with pytest.raises(spack.error.SpackError): s.concretize()
def test_spec_formatting(self): spec = Spec("multivalue-variant cflags=-O2") spec.concretize() # Since the default is the full spec see if the string rep of # spec is the same as the output of spec.format() # ignoring whitespace (though should we?) and ignoring dependencies spec_string = str(spec) idx = spec_string.index(' ^') assert spec_string[:idx] == spec.format().strip() # Testing named strings ie {string} and whether we get # the correct component # Mixed case intentional to test both package_segments = [("{NAME}", "name"), ("{VERSION}", "versions"), ("{compiler}", "compiler"), ("{compiler_flags}", "compiler_flags"), ("{variants}", "variants"), ("{architecture}", "architecture")] sigil_package_segments = [("{@VERSIONS}", '@' + str(spec.version)), ("{%compiler}", '%' + str(spec.compiler)), ("{arch=architecture}", ' arch=' + str(spec.architecture))] compiler_segments = [("{compiler.name}", "name"), ("{compiler.version}", "versions")] sigil_compiler_segments = [ ("{%compiler.name}", '%' + spec.compiler.name), ("{@compiler.version}", '@' + str(spec.compiler.version)) ] architecture_segments = [("{architecture.platform}", "platform"), ("{architecture.os}", "os"), ("{architecture.target}", "target")] other_segments = [('{spack_root}', spack.paths.spack_root), ('{spack_install}', spack.store.layout.root), ('{hash:7}', spec.dag_hash(7)), ('{/hash}', '/' + spec.dag_hash())] for named_str, prop in package_segments: expected = getattr(spec, prop, "") actual = spec.format(named_str) assert str(expected) == actual for named_str, expected in sigil_package_segments: actual = spec.format(named_str) assert expected == actual compiler = spec.compiler for named_str, prop in compiler_segments: expected = getattr(compiler, prop, "") actual = spec.format(named_str) assert str(expected) == actual for named_str, expected in sigil_compiler_segments: actual = spec.format(named_str) assert expected == actual arch = spec.architecture for named_str, prop in architecture_segments: expected = getattr(arch, prop, "") actual = spec.format(named_str) assert str(expected) == actual for named_str, expected in other_segments: actual = spec.format(named_str) assert expected == actual
def test_concretize_anonymous(self): with pytest.raises(spack.error.SpackError): s = Spec('+variant') s.concretize()
def test_invalid_dep(self, spec_str): spec = Spec(spec_str) with pytest.raises(spack.error.SpecError): spec.concretize()
def test_conflict_in_all_directives_true(self): s = Spec('when-directives-true') with pytest.raises(spack.error.SpackError): s.concretize()
def test_buildcache(mock_archive, tmpdir): # tweak patchelf to only do a download spec = Spec("patchelf") spec.concretize() pkg = spack.repo.get(spec) fake_fetchify(pkg.fetcher, pkg) mkdirp(os.path.join(pkg.prefix, "bin")) patchelfscr = os.path.join(pkg.prefix, "bin", "patchelf") f = open(patchelfscr, 'w') body = """#!/bin/bash echo $PATH""" f.write(body) f.close() st = os.stat(patchelfscr) os.chmod(patchelfscr, st.st_mode | stat.S_IEXEC) # Install the test package spec = Spec('trivial-install-test-package') spec.concretize() assert spec.concrete pkg = spec.package fake_fetchify(mock_archive.url, pkg) pkg.do_install() pkghash = '/' + spec.dag_hash(7) # Put some non-relocatable file in there filename = os.path.join(spec.prefix, "dummy.txt") with open(filename, "w") as script: script.write(spec.prefix) # Create an absolute symlink linkname = os.path.join(spec.prefix, "link_to_dummy.txt") os.symlink(filename, linkname) # Create the build cache and # put it directly into the mirror mirror_path = os.path.join(str(tmpdir), 'test-mirror') spack.mirror.create(mirror_path, specs=[]) # register mirror with spack config mirrors = {'spack-mirror-test': 'file://' + mirror_path} spack.config.set('mirrors', mirrors) stage = spack.stage.Stage(mirrors['spack-mirror-test'], name="build_cache", keep=True) stage.create() # setup argument parser parser = argparse.ArgumentParser() buildcache.setup_parser(parser) # Create a private key to sign package with if gpg2 available if has_gnupg2(): spack.util.gpg.Gpg.create(name='test key 1', expires='0', email='*****@*****.**', comment='Spack test key') # Create build cache with signing args = parser.parse_args(['create', '-d', mirror_path, str(spec)]) buildcache.buildcache(parser, args) # Uninstall the package pkg.do_uninstall(force=True) # test overwrite install args = parser.parse_args(['install', '-f', str(pkghash)]) buildcache.buildcache(parser, args) files = os.listdir(spec.prefix) assert 'link_to_dummy.txt' in files assert 'dummy.txt' in files assert os.path.realpath(os.path.join( spec.prefix, 'link_to_dummy.txt')) == os.path.realpath( os.path.join(spec.prefix, 'dummy.txt')) # create build cache with relative path and signing args = parser.parse_args( ['create', '-d', mirror_path, '-f', '-r', str(spec)]) buildcache.buildcache(parser, args) # Uninstall the package pkg.do_uninstall(force=True) # install build cache with verification args = parser.parse_args(['install', str(spec)]) buildcache.install_tarball(spec, args) # test overwrite install args = parser.parse_args(['install', '-f', str(pkghash)]) buildcache.buildcache(parser, args) files = os.listdir(spec.prefix) assert 'link_to_dummy.txt' in files assert 'dummy.txt' in files assert os.path.realpath(os.path.join( spec.prefix, 'link_to_dummy.txt')) == os.path.realpath( os.path.join(spec.prefix, 'dummy.txt')) else: # create build cache without signing args = parser.parse_args( ['create', '-d', mirror_path, '-f', '-u', str(spec)]) buildcache.buildcache(parser, args) # Uninstall the package pkg.do_uninstall(force=True) # install build cache without verification args = parser.parse_args(['install', '-u', str(spec)]) buildcache.install_tarball(spec, args) files = os.listdir(spec.prefix) assert 'link_to_dummy.txt' in files assert 'dummy.txt' in files assert os.path.realpath(os.path.join( spec.prefix, 'link_to_dummy.txt')) == os.path.realpath( os.path.join(spec.prefix, 'dummy.txt')) # test overwrite install without verification args = parser.parse_args(['install', '-f', '-u', str(pkghash)]) buildcache.buildcache(parser, args) # create build cache with relative path args = parser.parse_args( ['create', '-d', mirror_path, '-f', '-r', '-u', str(pkghash)]) buildcache.buildcache(parser, args) # Uninstall the package pkg.do_uninstall(force=True) # install build cache args = parser.parse_args(['install', '-u', str(spec)]) buildcache.install_tarball(spec, args) # test overwrite install args = parser.parse_args(['install', '-f', '-u', str(pkghash)]) buildcache.buildcache(parser, args) files = os.listdir(spec.prefix) assert 'link_to_dummy.txt' in files assert 'dummy.txt' in files assert os.path.realpath(os.path.join( spec.prefix, 'link_to_dummy.txt')) == os.path.realpath( os.path.join(spec.prefix, 'dummy.txt')) # Validate the relocation information buildinfo = bindist.read_buildinfo_file(spec.prefix) assert (buildinfo['relocate_textfiles'] == ['dummy.txt']) assert (buildinfo['relocate_links'] == ['link_to_dummy.txt']) args = parser.parse_args(['list']) buildcache.buildcache(parser, args) args = parser.parse_args(['list', '-f']) buildcache.buildcache(parser, args) args = parser.parse_args(['list', 'trivial']) buildcache.buildcache(parser, args) # Copy a key to the mirror to have something to download shutil.copyfile(mock_gpg_keys_path + '/external.key', mirror_path + '/external.key') args = parser.parse_args(['keys']) buildcache.buildcache(parser, args) args = parser.parse_args(['keys', '-f']) buildcache.buildcache(parser, args) # unregister mirror with spack config mirrors = {} spack.config.set('mirrors', mirrors) shutil.rmtree(mirror_path) stage.destroy() # Remove cached binary specs since we deleted the mirror bindist._cached_specs = None
def test_dependency_extensions(self): s = Spec('extension2') s.concretize() deps = set(x.name for x in s.package.dependency_activations()) assert deps == set(['extension1'])
def test_yaml_multivalue(): spec = Spec('multivalue_variant foo="bar,baz"') spec.concretize() check_yaml_round_trip(spec)
def test_inheritance_of_patches(self): s = Spec('patch-inheritance') # Will error if inheritor package cannot find inherited patch files s.concretize()
def test_compiler_child(self): s = Spec('mpileaks%clang ^dyninst%gcc') s.concretize() self.assertTrue(s['mpileaks'].satisfies('%clang')) self.assertTrue(s['dyninst'].satisfies('%gcc'))
def test_compiler_flags_from_user_are_grouped(self): spec = Spec('a%gcc cflags="-O -foo-flag foo-val" platform=test') spec.concretize() cflags = spec.compiler_flags['cflags'] assert any(x == '-foo-flag foo-val' for x in cflags)
def test_conflicts_in_spec(self, conflict_spec): s = Spec(conflict_spec) with pytest.raises(spack.error.SpackError): s.concretize()
def test_compiler_child(self): s = Spec('mpileaks%clang target=x86_64 ^dyninst%gcc') s.concretize() assert s['mpileaks'].satisfies('%clang') assert s['dyninst'].satisfies('%gcc')
def test_concrete_spec(config, builtin_mock): spec = Spec('mpileaks+debug~opt') spec.concretize() check_yaml_round_trip(spec)
def test_unsatisfiable_multi_value_variant(self): # Semantics for a multi-valued variant is different # Depending on whether the spec is concrete or not a = make_spec('multivalue-variant foo="bar"', concrete=True) spec_str = 'multivalue-variant foo="bar,baz"' b = Spec(spec_str) assert not a.satisfies(b) assert not a.satisfies(spec_str) # A concrete spec cannot be constrained further with pytest.raises(UnsatisfiableSpecError): a.constrain(b) a = Spec('multivalue-variant foo="bar"') spec_str = 'multivalue-variant foo="bar,baz"' b = Spec(spec_str) # The specs are abstract and they **could** be constrained assert a.satisfies(b) assert a.satisfies(spec_str) # An abstract spec can instead be constrained assert a.constrain(b) a = make_spec('multivalue-variant foo="bar,baz"', concrete=True) spec_str = 'multivalue-variant foo="bar,baz,quux"' b = Spec(spec_str) assert not a.satisfies(b) assert not a.satisfies(spec_str) # A concrete spec cannot be constrained further with pytest.raises(UnsatisfiableSpecError): a.constrain(b) a = Spec('multivalue-variant foo="bar,baz"') spec_str = 'multivalue-variant foo="bar,baz,quux"' b = Spec(spec_str) # The specs are abstract and they **could** be constrained assert a.satisfies(b) assert a.satisfies(spec_str) # An abstract spec can instead be constrained assert a.constrain(b) # ...but will fail during concretization if there are # values in the variant that are not allowed with pytest.raises(InvalidVariantValueError): a.concretize() # This time we'll try to set a single-valued variant a = Spec('multivalue-variant fee="bar"') spec_str = 'multivalue-variant fee="baz"' b = Spec(spec_str) # The specs are abstract and they **could** be constrained, # as before concretization I don't know which type of variant # I have (if it is not a BV) assert a.satisfies(b) assert a.satisfies(spec_str) # A variant cannot be parsed as single-valued until we try to # concretize. This means that we can constrain the variant above assert a.constrain(b) # ...but will fail during concretization if there are # multiple values set with pytest.raises(MultipleValuesInExclusiveVariantError): a.concretize()
def test_specs_staging(config): """Make sure we achieve the best possible staging for the following spec DAG:: a /| c b |\ e d |\ f g In this case, we would expect 'c', 'e', 'f', and 'g' to be in the first stage, and then 'd', 'b', and 'a' to be put in the next three stages, respectively. """ current_system = sys_type() config_compilers = config.get_config('compilers') first_compiler = config_compilers[0] compiler_spec = first_compiler['compiler']['spec'] # Whatever that first compiler in the configuration was, let's make sure # we mock up an entry like we'd find in os-container-mapping.yaml which # has that compiler. mock_containers = {} mock_containers[current_system] = { "image": "dontcare", "compilers": [{ "name": compiler_spec, }], } default = ('build', 'link') g = MockPackage('g', [], []) f = MockPackage('f', [], []) e = MockPackage('e', [], []) d = MockPackage('d', [f, g], [default, default]) c = MockPackage('c', [], []) b = MockPackage('b', [d, e], [default, default]) a = MockPackage('a', [b, c], [default, default]) mock_repo = MockPackageMultiRepo([a, b, c, d, e, f, g]) with repo.swap(mock_repo): # Now we'll ask for the root package to be compiled with whatever that # first compiler in the configuration was. spec_a = Spec('a%{0}'.format(compiler_spec)) spec_a.concretize() spec_a_label = spec_deps_key_label(spec_a)[1] spec_b_label = spec_deps_key_label(spec_a['b'])[1] spec_c_label = spec_deps_key_label(spec_a['c'])[1] spec_d_label = spec_deps_key_label(spec_a['d'])[1] spec_e_label = spec_deps_key_label(spec_a['e'])[1] spec_f_label = spec_deps_key_label(spec_a['f'])[1] spec_g_label = spec_deps_key_label(spec_a['g'])[1] spec_labels, dependencies, stages = stage_spec_jobs([spec_a], mock_containers, current_system) assert (len(stages) == 4) assert (len(stages[0]) == 4) assert (spec_c_label in stages[0]) assert (spec_e_label in stages[0]) assert (spec_f_label in stages[0]) assert (spec_g_label in stages[0]) assert (len(stages[1]) == 1) assert (spec_d_label in stages[1]) assert (len(stages[2]) == 1) assert (spec_b_label in stages[2]) assert (len(stages[3]) == 1) assert (spec_a_label in stages[3])
def test_indirect_unsatisfied_single_valued_variant(self): spec = Spec('singlevalue-variant-dependent') spec.concretize() assert '[email protected]' not in spec
def test_error_message_unknown_variant(self): s = Spec('mpileaks +unknown') with pytest.raises(UnknownVariantError, match=r'package has no such'): s.concretize()
def test_concretize_anonymous_dep(self, spec_str): with pytest.raises(spack.error.SpackError): s = Spec(spec_str) s.concretize()
def test_concretize_dependent_with_singlevalued_variant_type(self): s = Spec('singlevalue-variant-dependent-type') s.concretize()
def concretize_difficult_packages(self, a, b): """Test a couple of large packages that are often broken due to current limitations in the concretizer""" s = Spec(a + '@' + b) s.concretize() assert s[a].version == ver(b)