concretizer: account for test dependencies only when required

This commit is contained in:
Massimiliano Culpo 2020-10-22 14:26:11 +02:00 committed by Todd Gamblin
parent 346beedfd4
commit ae1ef85af5
3 changed files with 38 additions and 39 deletions

View File

@ -593,8 +593,10 @@ def one_of_iff(self, head, versions):
self.backend.add_rule([], [head_atom, more_than_1])
self.backend.add_rule([], [head_atom, -at_least_1])
def solve(self, solver_setup, specs, dump=None, nmodels=0,
timers=False, stats=False):
def solve(
self, solver_setup, specs, dump=None, nmodels=0,
timers=False, stats=False, tests=False
):
timer = Timer()
# Initialize the control object for the solver
@ -607,7 +609,7 @@ def solve(self, solver_setup, specs, dump=None, nmodels=0,
self.assumptions = []
with self.control.backend() as backend:
self.backend = backend
solver_setup.setup(self, specs)
solver_setup.setup(self, specs, tests=tests)
timer.phase("setup")
# read in the main ASP program and display logic -- these are
@ -837,7 +839,7 @@ def package_compiler_defaults(self, pkg):
self.gen.fact(fn.node_compiler_preference(
pkg.name, cspec.name, cspec.version, i))
def pkg_rules(self, pkg):
def pkg_rules(self, pkg, tests):
pkg = packagize(pkg)
# versions
@ -888,7 +890,7 @@ def pkg_rules(self, pkg):
self.package_compiler_defaults(pkg)
# dependencies
self.package_dependencies_rules(pkg)
self.package_dependencies_rules(pkg, tests)
# virtual preferences
self.virtual_preferences(
@ -898,7 +900,7 @@ def pkg_rules(self, pkg):
)
)
def package_dependencies_rules(self, pkg):
def package_dependencies_rules(self, pkg, tests):
"""Translate 'depends_on' directives into ASP logic."""
for name, conditions in sorted(pkg.dependencies.items()):
for cond, dep in sorted(conditions.items()):
@ -906,6 +908,10 @@ def package_dependencies_rules(self, pkg):
named_cond.name = named_cond.name or pkg.name
for t in sorted(dep.type):
# Skip test dependencies if they're not requested
if t == 'test' and (not tests or pkg.name not in tests):
continue
if cond == spack.spec.Spec():
self.gen.fact(
fn.declared_dependency(
@ -1411,7 +1417,7 @@ def define_compiler_version_constraints(self):
)
self.gen.newline()
def setup(self, driver, specs):
def setup(self, driver, specs, tests=False):
"""Generate an ASP program with relevant constraints for specs.
This calls methods on the solve driver to set up the problem with
@ -1464,7 +1470,7 @@ def setup(self, driver, specs):
self.gen.h1('Package Constraints')
for pkg in sorted(pkgs):
self.gen.h2('Package rules: %s' % pkg)
self.pkg_rules(pkg)
self.pkg_rules(pkg, tests=tests)
self.gen.h2('Package preferences: %s' % pkg)
self.preferred_variants(pkg)
self.preferred_targets(pkg)
@ -1735,7 +1741,7 @@ def highlight(string):
#
# These are handwritten parts for the Spack ASP model.
#
def solve(specs, dump=(), models=0, timers=False, stats=False):
def solve(specs, dump=(), models=0, timers=False, stats=False, tests=False):
"""Solve for a stable model of specs.
Arguments:
@ -1748,4 +1754,4 @@ def solve(specs, dump=(), models=0, timers=False, stats=False):
driver.out = sys.stdout
setup = SpackSolverSetup()
return driver.solve(setup, specs, dump, models, timers, stats)
return driver.solve(setup, specs, dump, models, timers, stats, tests)

View File

@ -2446,7 +2446,7 @@ def _new_concretize(self, tests=False):
raise spack.error.SpecError(
"Spec has no name; cannot concretize an anonymous spec")
result = spack.solver.asp.solve([self])
result = spack.solver.asp.solve([self], tests=tests)
if not result.satisfiable:
result.print_cores()
raise spack.error.UnsatisfiableSpecError(

View File

@ -2,12 +2,12 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""
These tests check Spec DAG operations using dummy packages.
"""
import pytest
import spack.architecture
import spack.error
import spack.package
from spack.spec import Spec
@ -90,6 +90,11 @@ def test_installed_deps():
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',)
@ -152,7 +157,12 @@ def test_specify_preinstalled_dep():
@pytest.mark.usefixtures('config')
def test_conditional_dep_with_user_constraints():
@pytest.mark.parametrize('spec_str,expr_str,expected', [
('x ^y@2', 'y@2', True),
('x@1', 'y', False),
('x', 'y@3', True)
])
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
@ -171,27 +181,15 @@ def test_conditional_dep_with_user_constraints():
mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions)
with spack.repo.swap(mock_repo):
spec = Spec('x ^y@2')
spec = Spec(spec_str)
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)
result = expr_str in spec
assert result is expected, '{0} in {1}'.format(expr_str, spec)
@pytest.mark.usefixtures('mutable_mock_repo', 'config')
class TestSpecDag(object):
def test_conflicting_package_constraints(self, set_dependency):
set_dependency('mpileaks', 'mpich@1.0')
set_dependency('callpath', 'mpich@2.0')
@ -387,17 +385,12 @@ def test_unsatisfiable_architecture(self, set_dependency):
with pytest.raises(spack.spec.UnsatisfiableArchitectureSpecError):
spec.normalize()
def test_invalid_dep(self):
spec = Spec('libelf ^mpich')
with pytest.raises(spack.spec.InvalidDependencyError):
spec.concretize()
spec = Spec('libelf ^libdwarf')
with pytest.raises(spack.spec.InvalidDependencyError):
spec.concretize()
spec = Spec('mpich ^dyninst ^libelf')
with pytest.raises(spack.spec.InvalidDependencyError):
@pytest.mark.parametrize('spec_str', [
'libelf ^mpich', 'libelf ^libdwarf', 'mpich ^dyninst ^libelf'
])
def test_invalid_dep(self, spec_str):
spec = Spec(spec_str)
with pytest.raises(spack.error.SpecError):
spec.concretize()
def test_equal(self):