tests for variant concretization

This commit is contained in:
Todd Gamblin 2015-04-27 00:45:59 -07:00
parent 535c1fac87
commit 793b842f99
2 changed files with 44 additions and 12 deletions

View file

@ -294,8 +294,13 @@ def __str__(self):
class VariantMap(HashableMap):
def satisfies(self, other, self_is_concrete):
if self_is_concrete:
def __init__(self, spec):
super(VariantMap, self).__init__()
self.spec = spec
def satisfies(self, other):
if self.spec._concrete:
return all(k in self and self[k].enabled == other[k].enabled
for k in other)
else:
@ -303,8 +308,8 @@ def satisfies(self, other, self_is_concrete):
for k in other if k in self)
def constrain(self, other, other_is_concrete):
if other_is_concrete:
def constrain(self, other):
if other.spec._concrete:
for k in self:
if k not in other:
raise UnsatisfiableVariantSpecError(self[k], '<absent>')
@ -316,6 +321,18 @@ def constrain(self, other, other_is_concrete):
else:
self[k] = other[k].copy()
@property
def concrete(self):
return self.spec._concrete or all(
v in self for v in self.spec.package.variants)
def copy(self):
clone = VariantMap(None)
for name, variant in self.items():
clone[name] = variant.copy()
return clone
def __str__(self):
sorted_keys = sorted(self.keys())
@ -361,10 +378,11 @@ def __init__(self, spec_like, *dep_like, **kwargs):
self.name = other.name
self.dependents = other.dependents
self.versions = other.versions
self.variants = other.variants
self.architecture = other.architecture
self.compiler = other.compiler
self.dependencies = other.dependencies
self.variants = other.variants
self.variants.spec = self
# Specs are by default not assumed to be normal, but in some
# cases we've read them from a file want to assume normal.
@ -457,14 +475,15 @@ def virtual(self):
@property
def concrete(self):
"""A spec is concrete if it can describe only ONE build of a package.
If any of the name, version, architecture, compiler, or depdenencies
are ambiguous,then it is not concrete.
If any of the name, version, architecture, compiler,
variants, or depdenencies are ambiguous,then it is not concrete.
"""
if self._concrete:
return True
self._concrete = bool(not self.virtual
and self.versions.concrete
and self.variants.concrete
and self.architecture
and self.compiler and self.compiler.concrete
and self.dependencies.concrete)
@ -947,7 +966,7 @@ def constrain(self, other, **kwargs):
self.compiler = other.compiler
self.versions.intersect(other.versions)
self.variants.constrain(other.variants, other._concrete)
self.variants.constrain(other.variants)
self.architecture = self.architecture or other.architecture
if constrain_deps:
@ -1020,7 +1039,7 @@ def satisfies(self, other, **kwargs):
if s and o and not s.satisfies(o):
return False
if not self.variants.satisfies(other.variants, self._concrete):
if not self.variants.satisfies(other.variants):
return False
# Architecture satisfaction is currently just string equality.
@ -1089,11 +1108,12 @@ def _dup(self, other, **kwargs):
# Local node attributes get copied first.
self.name = other.name
self.versions = other.versions.copy()
self.variants = other.variants.copy()
self.architecture = other.architecture
self.compiler = other.compiler.copy() if other.compiler else None
self.dependents = DependencyMap()
self.dependencies = DependencyMap()
self.variants = other.variants.copy()
self.variants.spec = self
# If we copy dependencies, preserve DAG structure in the new spec
if kwargs.get('deps', True):
@ -1429,7 +1449,7 @@ def spec(self):
spec = Spec.__new__(Spec)
spec.name = self.token.value
spec.versions = VersionList()
spec.variants = VariantMap()
spec.variants = VariantMap(spec)
spec.architecture = None
spec.compiler = None
spec.dependents = DependencyMap()

View file

@ -35,7 +35,13 @@ def check_spec(self, abstract, concrete):
self.assertEqual(abstract.versions, concrete.versions)
if abstract.variants:
self.assertEqual(abstract.versions, concrete.versions)
for name in abstract.variants:
avariant = abstract.variants[name]
cvariant = concrete.variants[name]
self.assertEqual(avariant.enabled, cvariant.enabled)
for name in abstract.package.variants:
self.assertTrue(name in concrete.variants)
if abstract.compiler and abstract.compiler.concrete:
self.assertEqual(abstract.compiler, concrete.compiler)
@ -66,6 +72,12 @@ def test_concretize_dag(self):
self.check_concretize('libelf')
def test_concretize_variant(self):
self.check_concretize('mpich+debug')
self.check_concretize('mpich~debug')
self.check_concretize('mpich')
def test_concretize_with_virtual(self):
self.check_concretize('mpileaks ^mpi')
self.check_concretize('mpileaks ^mpi@:1.1')