Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build caching: support package hash for swig #14153

Merged
merged 3 commits into from
Dec 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
58 changes: 34 additions & 24 deletions lib/spack/spack/test/packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
import spack.directives


def _generate_content_strip_name(spec):
content = package_content(spec)
return content.replace(spec.package.__class__.__name__, '')


@pytest.mark.usefixtures('config', 'mock_packages')
class TestPackage(object):
def test_load_package(self):
Expand Down Expand Up @@ -53,38 +58,43 @@ def test_package_class_names(self):
assert '_3db' == mod_to_class('3db')

def test_content_hash_all_same_but_patch_contents(self):
spec1 = Spec("hash-test1@1.1")
spec2 = Spec("hash-test2@1.1")
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__, '')
spec1 = Spec("hash-test1@1.1").concretized()
spec2 = Spec("hash-test2@1.1").concretized()
content1 = _generate_content_strip_name(spec1)
content2 = _generate_content_strip_name(spec2)
assert spec1.package.content_hash(content=content1) != \
spec2.package.content_hash(content=content2)

def test_content_hash_different_variants(self):
spec1 = Spec("hash-test1@1.2 +variantx")
spec2 = Spec("hash-test2@1.2 ~variantx")
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__, '')
spec1 = Spec("hash-test1@1.2 +variantx").concretized()
spec2 = Spec("hash-test2@1.2 ~variantx").concretized()
content1 = _generate_content_strip_name(spec1)
content2 = _generate_content_strip_name(spec2)
assert spec1.package.content_hash(content=content1) == \
spec2.package.content_hash(content=content2)

def test_content_hash_cannot_get_details_from_ast(self):
"""Packages hash-test1 and hash-test3 would be considered the same
except that hash-test3 conditionally executes a phase based on
a "when" directive that Spack cannot evaluate by examining the
AST. This test ensures that Spack can compute a content hash
for hash-test3. If Spack cannot determine when a phase applies,
it adds it by default, so the test also ensures that the hashes
differ where Spack includes a phase on account of AST-examination
failure.
"""
spec3 = Spec("hash-test1@1.7").concretized()
spec4 = Spec("hash-test3@1.7").concretized()
content3 = _generate_content_strip_name(spec3)
content4 = _generate_content_strip_name(spec4)
assert(spec3.package.content_hash(content=content3) !=
spec4.package.content_hash(content=content4))

def test_all_same_but_archive_hash(self):
spec1 = Spec("hash-test1@1.3")
spec2 = Spec("hash-test2@1.3")
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__, '')
spec1 = Spec("hash-test1@1.3").concretized()
spec2 = Spec("hash-test2@1.3").concretized()
content1 = _generate_content_strip_name(spec1)
content2 = _generate_content_strip_name(spec2)
assert spec1.package.content_hash(content=content1) != \
spec2.package.content_hash(content=content2)

Expand Down
13 changes: 11 additions & 2 deletions lib/spack/spack/util/package_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,17 @@ def visit_FunctionDef(self, node): # noqa
if node.decorator_list:
dec = node.decorator_list[0]
if isinstance(dec, ast.Call) and dec.func.id == 'when':
cond = dec.args[0].s
nodes.append((node, self.spec.satisfies(cond, strict=True)))
try:
cond = dec.args[0].s
nodes.append(
(node, self.spec.satisfies(cond, strict=True)))
except AttributeError:
# In this case the condition for the 'when' decorator is
# not a string literal (for example it may be a Python
# variable name). Therefore the function is added
# unconditionally since we don't know whether the
# constraint applies or not.
nodes.append((node, None))
else:
nodes.append((node, None))

Expand Down
9 changes: 8 additions & 1 deletion var/spack/repos/builtin.mock/packages/hash-test1/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class HashTest1(Package):
version('1.2', 'b' * 32)
version('1.3', 'c' * 32)
version('1.4', 'd' * 32)
version('1.5', 'd' * 32)
version('1.6', 'e' * 32)
version('1.7', 'f' * 32)

patch('patch1.patch', when="@1.1")
patch('patch2.patch', when="@1.4")
Expand All @@ -34,6 +37,10 @@ def install(self, spec, prefix):
print("install 1")
os.listdir(os.getcwd())

@when('@1.5')
@when('@1.5:')
def install(self, spec, prefix):
os.listdir(os.getcwd())

@when('@1.5,1.6')
def extra_phase(self, spec, prefix):
pass
42 changes: 42 additions & 0 deletions var/spack/repos/builtin.mock/packages/hash-test3/package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

import os


class HashTest3(Package):
"""Used to test package hashing
"""

homepage = "http://www.hashtest3.org"
url = "http://www.hashtest1.org/downloads/hashtest3-1.1.tar.bz2"

version('1.2', 'b' * 32)
version('1.3', 'c' * 32)
version('1.5', 'd' * 32)
version('1.6', 'e' * 32)
version('1.7', 'f' * 32)

variant('variantx', default=False, description='Test variant X')
variant('varianty', default=False, description='Test variant Y')

def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
pass

@when('@:1.4')
def install(self, spec, prefix):
print("install 1")
os.listdir(os.getcwd())

@when('@1.5:')
def install(self, spec, prefix):
os.listdir(os.getcwd())

for _version_constraint in ['@1.5', '@1.6']:
@when(_version_constraint)
def extra_phase(self, spec, prefix):
pass