def test_add_to_upstream_after_downstream(upstream_and_downstream_db): """An upstream DB can add a package after it is installed in the downstream DB. When a package is recorded as installed in both, the results should refer to the downstream DB. """ upstream_write_db, upstream_db, upstream_layout,\ downstream_db, downstream_layout = (upstream_and_downstream_db) mock_repo = MockPackageMultiRepo() mock_repo.add_package('x', [], []) with spack.repo.use_repositories(mock_repo): spec = spack.spec.Spec('x') spec.concretize() downstream_db.add(spec, downstream_layout) upstream_write_db.add(spec, upstream_layout) upstream_db._read() upstream, record = downstream_db.query_by_spec_hash(spec.dag_hash()) # Even though the package is recorded as installed in the upstream DB, # we prefer the locally-installed instance assert not upstream qresults = downstream_db.query('x') assert len(qresults) == 1 queried_spec, = qresults try: orig_db = spack.store.db spack.store.db = downstream_db assert queried_spec.prefix == downstream_layout.path_for_spec(spec) finally: spack.store.db = orig_db
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', ) mock_repo = MockPackageMultiRepo() x = mock_repo.add_package('x', [], []) z = mock_repo.add_package('z', [], []) y = mock_repo.add_package('y', [z], [test_only]) w = mock_repo.add_package('w', [x, y], [test_only, default]) with spack.repo.use_repositories(mock_repo): spec = Spec('w') spec.concretize(tests=(w.name, )) assert ('x' in spec) assert ('z' not in spec)
def test_removed_upstream_dep(upstream_and_downstream_db): upstream_write_db, upstream_db, upstream_layout,\ downstream_db, downstream_layout = (upstream_and_downstream_db) default = ('build', 'link') mock_repo = MockPackageMultiRepo() z = mock_repo.add_package('z', [], []) mock_repo.add_package('y', [z], [default]) with spack.repo.use_repositories(mock_repo): spec = spack.spec.Spec('y') spec.concretize() upstream_write_db.add(spec['z'], upstream_layout) upstream_db._read() new_spec = spack.spec.Spec('y') new_spec.concretize() downstream_db.add(new_spec, downstream_layout) upstream_write_db.remove(new_spec['z']) upstream_db._read() new_downstream = spack.database.Database(downstream_db.root, upstream_dbs=[upstream_db]) new_downstream._fail_when_missing_deps = True with pytest.raises(spack.database.MissingDependenciesError): new_downstream._read()
def test_conditional_dep_with_user_constraints(): """This sets up packages X->Y such that X depends on Y conditionally. It then constructs a Spec with X but with no constraints on X, so that the initial normalization pass cannot determine whether the constraints are met to add the dependency; this checks whether a user-specified constraint on Y is applied properly. """ default = ('build', 'link') mock_repo = MockPackageMultiRepo() y = mock_repo.add_package('y', [], []) x_on_y_conditions = {y.name: {'x@2:': 'y'}} mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions) with spack.repo.swap(mock_repo): spec = Spec('x ^y@2') spec.concretize() assert ('y@2' in spec) with spack.repo.swap(mock_repo): spec = Spec('x@1') spec.concretize() assert ('y' not in spec) with spack.repo.swap(mock_repo): spec = Spec('x') spec.concretize() assert ('y@3' in spec)
def test_conditional_dep_with_user_constraints(spec_str, expr_str, expected): """This sets up packages X->Y such that X depends on Y conditionally. It then constructs a Spec with X but with no constraints on X, so that the initial normalization pass cannot determine whether the constraints are met to add the dependency; this checks whether a user-specified constraint on Y is applied properly. """ # FIXME: We need to tweak optimization rules to make this test # FIXME: not prefer a DAG with fewer nodes wrt more recent # FIXME: versions of the package if spack.config.get('config:concretizer') == 'clingo': pytest.xfail('Clingo optimization rules prefer to trim a node') default = ('build', 'link') mock_repo = MockPackageMultiRepo() y = mock_repo.add_package('y', [], []) x_on_y_conditions = {y.name: {'x@2:': 'y'}} mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions) with spack.repo.use_repositories(mock_repo): spec = Spec(spec_str) spec.concretize() result = expr_str in spec assert result is expected, '{0} in {1}'.format(expr_str, spec)
def test_mock_repo_is_virtual(): mock_repo = MockPackageMultiRepo() # current implementation is always false assert mock_repo.is_virtual("foo") is False assert mock_repo.is_virtual("bar") is False assert mock_repo.is_virtual("baz") is False
def test_spec_installed_upstream(upstream_and_downstream_db, config, monkeypatch): """Test whether Spec.installed_upstream() works.""" upstream_write_db, upstream_db, upstream_layout, \ downstream_db, downstream_layout = upstream_and_downstream_db # a known installed spec should say that it's installed mock_repo = MockPackageMultiRepo() mock_repo.add_package('x', [], []) with spack.repo.use_repositories(mock_repo): spec = spack.spec.Spec("x").concretized() assert not spec.installed assert not spec.installed_upstream upstream_write_db.add(spec, upstream_layout) upstream_db._read() monkeypatch.setattr(spack.store, "db", downstream_db) assert spec.installed assert spec.installed_upstream assert spec.copy().installed # an abstract spec should say it's not installed spec = spack.spec.Spec("not-a-real-package") assert not spec.installed assert not spec.installed_upstream
def test_save_dependency_spec_jsons_subset(tmpdir, config): output_path = str(tmpdir.mkdir('spec_jsons')) default = ('build', 'link') mock_repo = MockPackageMultiRepo() g = mock_repo.add_package('g', [], []) f = mock_repo.add_package('f', [], []) e = mock_repo.add_package('e', [], []) d = mock_repo.add_package('d', [f, g], [default, default]) c = mock_repo.add_package('c', [], []) b = mock_repo.add_package('b', [d, e], [default, default]) mock_repo.add_package('a', [b, c], [default, default]) with repo.use_repositories(mock_repo): spec_a = Spec('a') spec_a.concretize() b_spec = spec_a['b'] c_spec = spec_a['c'] spec_a_json = spec_a.to_json(hash=ht.build_hash) save_dependency_specfiles(spec_a_json, output_path, ['b', 'c']) assert check_specs_equal(b_spec, os.path.join(output_path, 'b.json')) assert check_specs_equal(c_spec, os.path.join(output_path, 'c.json'))
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. """ default = ('build', 'link') mock_repo = MockPackageMultiRepo() g = mock_repo.add_package('g', [], []) f = mock_repo.add_package('f', [], []) e = mock_repo.add_package('e', [], []) d = mock_repo.add_package('d', [f, g], [default, default]) c = mock_repo.add_package('c', [], []) b = mock_repo.add_package('b', [d, e], [default, default]) mock_repo.add_package('a', [b, c], [default, default]) with repo.use_repositories(mock_repo): spec_a = Spec('a') spec_a.concretize() spec_a_label = ci.spec_deps_key_label(spec_a)[1] spec_b_label = ci.spec_deps_key_label(spec_a['b'])[1] spec_c_label = ci.spec_deps_key_label(spec_a['c'])[1] spec_d_label = ci.spec_deps_key_label(spec_a['d'])[1] spec_e_label = ci.spec_deps_key_label(spec_a['e'])[1] spec_f_label = ci.spec_deps_key_label(spec_a['f'])[1] spec_g_label = ci.spec_deps_key_label(spec_a['g'])[1] spec_labels, dependencies, stages = ci.stage_spec_jobs([spec_a]) 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_115_reindex_with_packages_not_in_repo(mutable_database): # Dont add any package definitions to this repository, the idea is that # packages should not have to be defined in the repository once they # are installed with spack.repo.use_repositories(MockPackageMultiRepo()): spack.store.store.reindex() _check_db_sanity(mutable_database)
def test_installed_deps(): """Preinstall a package P with a constrained build dependency D, then concretize a dependent package which also depends on P and D, specifying that the installed instance of P should be used. In this case, D should not be constrained by P since P is already built. """ default = ('build', 'link') build_only = ('build', ) mock_repo = MockPackageMultiRepo() e = mock_repo.add_package('e', [], []) d = mock_repo.add_package('d', [], []) c_conditions = {d.name: {'c': 'd@2'}, e.name: {'c': 'e@2'}} c = mock_repo.add_package('c', [d, e], [build_only, default], conditions=c_conditions) b = mock_repo.add_package('b', [d, e], [default, default]) mock_repo.add_package('a', [b, c], [default, default]) with spack.repo.swap(mock_repo): c_spec = Spec('c') c_spec.concretize() assert c_spec['d'].version == spack.version.Version('2') c_installed = spack.spec.Spec.from_dict(c_spec.to_dict()) for spec in c_installed.traverse(): setattr(spec.package, 'installed', True) a_spec = Spec('a') a_spec._add_dependency(c_installed, default) a_spec.concretize() assert a_spec['d'].version == spack.version.Version('3') assert a_spec['e'].version == spack.version.Version('2')
def test_cannot_write_upstream(tmpdir_factory, gen_mock_layout): roots = [str(tmpdir_factory.mktemp(x)) for x in ['a', 'b']] layouts = [gen_mock_layout(x) for x in ['/ra/', '/rb/']] mock_repo = MockPackageMultiRepo() mock_repo.add_package('x', [], []) # Instantiate the database that will be used as the upstream DB and make # sure it has an index file upstream_db_independent = spack.database.Database(roots[1]) with upstream_db_independent.write_transaction(): pass upstream_dbs = spack.store._construct_upstream_dbs_from_install_roots( [roots[1]], _test=True) with spack.repo.use_repositories(mock_repo): spec = spack.spec.Spec('x') spec.concretize() with pytest.raises(spack.database.ForbiddenLockError): upstream_dbs[0].add(spec, layouts[1])
def test_query_installed_when_package_unknown(database): """Test that we can query the installation status of a spec when we don't know its package.py """ with spack.repo.use_repositories(MockPackageMultiRepo()): specs = database.query('mpileaks') for s in specs: # Assert that we can query the installation methods even though we # don't have the package.py available assert s.installed assert not s.installed_upstream with pytest.raises(spack.repo.UnknownNamespaceError): s.package
def test_installed_deps(monkeypatch): """Preinstall a package P with a constrained build dependency D, then concretize a dependent package which also depends on P and D, specifying that the installed instance of P should be used. In this case, D should not be constrained by P since P is already built. """ # FIXME: this requires to concretize build deps separately if we are # FIXME: using the clingo based concretizer if spack.config.get('config:concretizer') == 'clingo': pytest.xfail('requires separate concretization of build dependencies') default = ('build', 'link') build_only = ('build',) mock_repo = MockPackageMultiRepo() e = mock_repo.add_package('e', [], []) d = mock_repo.add_package('d', [], []) c_conditions = { d.name: { 'c': 'd@2' }, e.name: { 'c': 'e@2' } } c = mock_repo.add_package('c', [d, e], [build_only, default], conditions=c_conditions) b = mock_repo.add_package('b', [d, e], [default, default]) mock_repo.add_package('a', [b, c], [default, default]) with spack.repo.use_repositories(mock_repo): c_spec = Spec('c') c_spec.concretize() assert c_spec['d'].version == spack.version.Version('2') c_installed = spack.spec.Spec.from_dict(c_spec.to_dict()) installed_names = [s.name for s in c_installed.traverse()] def _mock_installed(self): return self.name in installed_names monkeypatch.setattr(Spec, 'installed', _mock_installed) a_spec = Spec('a') a_spec._add_dependency(c_installed, default) a_spec.concretize() assert a_spec['d'].version == spack.version.Version('3') assert a_spec['e'].version == spack.version.Version('2')
def test_recursive_upstream_dbs(tmpdir_factory, gen_mock_layout): roots = [str(tmpdir_factory.mktemp(x)) for x in ['a', 'b', 'c']] layouts = [gen_mock_layout(x) for x in ['/ra/', '/rb/', '/rc/']] default = ('build', 'link') mock_repo = MockPackageMultiRepo() z = mock_repo.add_package('z', [], []) y = mock_repo.add_package('y', [z], [default]) mock_repo.add_package('x', [y], [default]) with spack.repo.use_repositories(mock_repo): spec = spack.spec.Spec('x') spec.concretize() db_c = spack.database.Database(roots[2]) db_c.add(spec['z'], layouts[2]) db_b = spack.database.Database(roots[1], upstream_dbs=[db_c]) db_b.add(spec['y'], layouts[1]) db_a = spack.database.Database(roots[0], upstream_dbs=[db_b, db_c]) db_a.add(spec['x'], layouts[0]) upstream_dbs_from_scratch = ( spack.store._construct_upstream_dbs_from_install_roots( [roots[1], roots[2]], _test=True)) db_a_from_scratch = spack.database.Database( roots[0], upstream_dbs=upstream_dbs_from_scratch) assert db_a_from_scratch.db_for_spec_hash( spec.dag_hash()) == (db_a_from_scratch) assert db_a_from_scratch.db_for_spec_hash( spec['y'].dag_hash()) == (upstream_dbs_from_scratch[0]) assert db_a_from_scratch.db_for_spec_hash( spec['z'].dag_hash()) == (upstream_dbs_from_scratch[1]) db_a_from_scratch._check_ref_counts() upstream_dbs_from_scratch[0]._check_ref_counts() upstream_dbs_from_scratch[1]._check_ref_counts() assert (db_a_from_scratch.installed_relatives(spec) == set( spec.traverse(root=False))) assert (db_a_from_scratch.installed_relatives( spec['z'], direction='parents') == set([spec, spec['y']]))
def test_architecture_deep_inheritance(self, mock_targets): """Make sure that indirect dependencies receive architecture information from the root even when partial architecture information is provided by an intermediate dependency. """ default_dep = ('link', 'build') mock_repo = MockPackageMultiRepo() bazpkg = mock_repo.add_package('bazpkg', [], []) barpkg = mock_repo.add_package('barpkg', [bazpkg], [default_dep]) mock_repo.add_package('foopkg', [barpkg], [default_dep]) with spack.repo.use_repositories(mock_repo): spec = Spec('foopkg %[email protected] os=CNL target=nocona' + ' ^barpkg os=SuSE11 ^bazpkg os=be') spec.concretize() for s in spec.traverse(root=False): assert s.architecture.target == spec.architecture.target
def test_installed_upstream(upstream_and_downstream_db): upstream_write_db, upstream_db, upstream_layout,\ downstream_db, downstream_layout = (upstream_and_downstream_db) default = ('build', 'link') mock_repo = MockPackageMultiRepo() x = mock_repo.add_package('x', [], []) z = mock_repo.add_package('z', [], []) y = mock_repo.add_package('y', [z], [default]) mock_repo.add_package('w', [x, y], [default, default]) with spack.repo.use_repositories(mock_repo): spec = spack.spec.Spec('w') spec.concretize() for dep in spec.traverse(root=False): upstream_write_db.add(dep, upstream_layout) upstream_db._read() for dep in spec.traverse(root=False): record = downstream_db.get_by_hash(dep.dag_hash()) assert record is not None with pytest.raises(spack.database.ForbiddenLockError): record = upstream_db.get_by_hash(dep.dag_hash()) new_spec = spack.spec.Spec('w') new_spec.concretize() downstream_db.add(new_spec, downstream_layout) for dep in new_spec.traverse(root=False): upstream, record = downstream_db.query_by_spec_hash( dep.dag_hash()) assert upstream assert record.path == upstream_layout.path_for_spec(dep) upstream, record = downstream_db.query_by_spec_hash( new_spec.dag_hash()) assert not upstream assert record.installed upstream_db._check_ref_counts() downstream_db._check_ref_counts()
def test_specify_preinstalled_dep(): """Specify the use of a preinstalled package during concretization with a transitive dependency that is only supplied by the preinstalled package. """ default = ('build', 'link') mock_repo = MockPackageMultiRepo() c = mock_repo.add_package('c', [], []) b = mock_repo.add_package('b', [c], [default]) mock_repo.add_package('a', [b], [default]) with spack.repo.use_repositories(mock_repo): b_spec = Spec('b') b_spec.concretize() for spec in b_spec.traverse(): setattr(spec.package, 'installed', True) a_spec = Spec('a') a_spec._add_dependency(b_spec, default) a_spec.concretize() assert set(x.name for x in a_spec.traverse()) == set(['a', 'b', 'c'])
def test_mock_package_possible_dependencies(): mock_repo = MockPackageMultiRepo() e = mock_repo.add_package('e') d = mock_repo.add_package('d', [e]) c = mock_repo.add_package('c', [d]) b = mock_repo.add_package('b', [d]) a = mock_repo.add_package('a', [b, c]) with spack.repo.use_repositories(mock_repo): assert set(a.possible_dependencies()) == set(['a', 'b', 'c', 'd', 'e']) assert set(b.possible_dependencies()) == set(['b', 'd', 'e']) assert set(c.possible_dependencies()) == set(['c', 'd', 'e']) assert set(d.possible_dependencies()) == set(['d', 'e']) assert set(e.possible_dependencies()) == set(['e']) assert set(a.possible_dependencies(transitive=False)) == set( ['a', 'b', 'c']) assert set(b.possible_dependencies(transitive=False)) == set( ['b', 'd']) assert set(c.possible_dependencies(transitive=False)) == set( ['c', 'd']) assert set(d.possible_dependencies(transitive=False)) == set( ['d', 'e']) assert set(e.possible_dependencies(transitive=False)) == set(['e'])