Spack tests no longer clutter var/spack/stage
- Tests use a session-scoped mock stage directory so as not to interfere with the real install. - Every test is forced to clean up after itself with an additional check. We now automatically assert that no new files have been added to `spack.stage_path` during each test. - This means that tests that fail installs now need to clean up their stages, but in all other cases the check is useful.
This commit is contained in:
parent
44bebd7a8f
commit
d14816cbaf
6 changed files with 158 additions and 113 deletions
|
@ -1405,6 +1405,7 @@ def build_process():
|
||||||
|
|
||||||
echo = logger.echo
|
echo = logger.echo
|
||||||
self.log()
|
self.log()
|
||||||
|
|
||||||
# Run post install hooks before build stage is removed.
|
# Run post install hooks before build stage is removed.
|
||||||
spack.hooks.post_install(self.spec)
|
spack.hooks.post_install(self.spec)
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,7 @@ def test_package_output(tmpdir, capsys, install_mockery, mock_fetch):
|
||||||
assert "'install'\nAFTER INSTALL" in out
|
assert "'install'\nAFTER INSTALL" in out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_install_output_on_build_error(builtin_mock, mock_archive, mock_fetch,
|
def test_install_output_on_build_error(builtin_mock, mock_archive, mock_fetch,
|
||||||
config, install_mockery, capfd):
|
config, install_mockery, capfd):
|
||||||
# capfd interferes with Spack's capturing
|
# capfd interferes with Spack's capturing
|
||||||
|
@ -161,6 +162,7 @@ def test_install_output_on_build_error(builtin_mock, mock_archive, mock_fetch,
|
||||||
assert 'configure: error: cannot run C compiled programs.' in out
|
assert 'configure: error: cannot run C compiled programs.' in out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_install_output_on_python_error(builtin_mock, mock_archive, mock_fetch,
|
def test_install_output_on_python_error(builtin_mock, mock_archive, mock_fetch,
|
||||||
config, install_mockery):
|
config, install_mockery):
|
||||||
out = install('failing-build', fail_on_error=False)
|
out = install('failing-build', fail_on_error=False)
|
||||||
|
@ -169,6 +171,7 @@ def test_install_output_on_python_error(builtin_mock, mock_archive, mock_fetch,
|
||||||
assert 'raise InstallError("Expected failure.")' in out
|
assert 'raise InstallError("Expected failure.")' in out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_install_with_source(
|
def test_install_with_source(
|
||||||
builtin_mock, mock_archive, mock_fetch, config, install_mockery):
|
builtin_mock, mock_archive, mock_fetch, config, install_mockery):
|
||||||
"""Verify that source has been copied into place."""
|
"""Verify that source has been copied into place."""
|
||||||
|
@ -180,6 +183,7 @@ def test_install_with_source(
|
||||||
os.path.join(src, 'configure'))
|
os.path.join(src, 'configure'))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_show_log_on_error(builtin_mock, mock_archive, mock_fetch,
|
def test_show_log_on_error(builtin_mock, mock_archive, mock_fetch,
|
||||||
config, install_mockery, capfd):
|
config, install_mockery, capfd):
|
||||||
"""Make sure --show-log-on-error works."""
|
"""Make sure --show-log-on-error works."""
|
||||||
|
|
|
@ -25,14 +25,16 @@
|
||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import shutil
|
import shutil
|
||||||
|
import re
|
||||||
|
|
||||||
import ordereddict_backport
|
import ordereddict_backport
|
||||||
|
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from llnl.util.filesystem import remove_linked_tree
|
||||||
|
|
||||||
import spack
|
import spack
|
||||||
import spack.architecture
|
import spack.architecture
|
||||||
import spack.database
|
import spack.database
|
||||||
|
@ -71,6 +73,64 @@ def no_chdir():
|
||||||
assert os.getcwd() == original_wd
|
assert os.getcwd() == original_wd
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='session', autouse=True)
|
||||||
|
def mock_stage(tmpdir_factory):
|
||||||
|
"""Mocks up a fake stage directory for use by tests."""
|
||||||
|
stage_path = spack.stage_path
|
||||||
|
new_stage = str(tmpdir_factory.mktemp('mock_stage'))
|
||||||
|
spack.stage_path = new_stage
|
||||||
|
yield new_stage
|
||||||
|
spack.stage_path = stage_path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='session')
|
||||||
|
def _ignore_stage_files():
|
||||||
|
"""Session-scoped helper for check_for_leftover_stage_files.
|
||||||
|
|
||||||
|
Used to track which leftover files in the stage have been seen.
|
||||||
|
"""
|
||||||
|
# to start with, ignore the .lock file at the stage root.
|
||||||
|
return set(['.lock'])
|
||||||
|
|
||||||
|
|
||||||
|
def remove_whatever_it_is(path):
|
||||||
|
"""Type-agnostic remove."""
|
||||||
|
if os.path.isfile(path):
|
||||||
|
os.remove(path)
|
||||||
|
elif os.path.islink(path):
|
||||||
|
remove_linked_tree(path)
|
||||||
|
else:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function', autouse=True)
|
||||||
|
def check_for_leftover_stage_files(request, mock_stage, _ignore_stage_files):
|
||||||
|
"""Ensure that each test leaves a clean stage when done.
|
||||||
|
|
||||||
|
This can be disabled for tests that are expected to dirty the stage
|
||||||
|
by adding::
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
|
|
||||||
|
to tests that need it.
|
||||||
|
"""
|
||||||
|
yield
|
||||||
|
|
||||||
|
files_in_stage = set()
|
||||||
|
if os.path.exists(spack.stage_path):
|
||||||
|
files_in_stage = set(
|
||||||
|
os.listdir(spack.stage_path)) - _ignore_stage_files
|
||||||
|
|
||||||
|
if 'disable_clean_stage_check' in request.keywords:
|
||||||
|
# clean up after tests that are expected to be dirty
|
||||||
|
for f in files_in_stage:
|
||||||
|
path = os.path.join(spack.stage_path, f)
|
||||||
|
remove_whatever_it_is(path)
|
||||||
|
else:
|
||||||
|
_ignore_stage_files |= files_in_stage
|
||||||
|
assert not files_in_stage
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
def mock_fetch_cache(monkeypatch):
|
def mock_fetch_cache(monkeypatch):
|
||||||
"""Substitutes spack.fetch_cache with a mock object that does nothing
|
"""Substitutes spack.fetch_cache with a mock object that does nothing
|
||||||
|
@ -193,7 +253,7 @@ def config(configuration_dir):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@pytest.fixture(scope='module')
|
||||||
def database(mock_stage, tmpdir_factory, builtin_mock, config):
|
def database(tmpdir_factory, builtin_mock, config):
|
||||||
"""Creates a mock database with some packages installed note that
|
"""Creates a mock database with some packages installed note that
|
||||||
the ref count for dyninst here will be 3, as it's recycled
|
the ref count for dyninst here will be 3, as it's recycled
|
||||||
across each install.
|
across each install.
|
||||||
|
@ -296,18 +356,8 @@ def refresh_db_on_exit(database):
|
||||||
database.refresh()
|
database.refresh()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
|
||||||
def mock_stage(tmpdir_factory):
|
|
||||||
"""Mocks up a fake stage directory for use by tests."""
|
|
||||||
stage_path = spack.stage_path
|
|
||||||
new_stage = str(tmpdir_factory.mktemp('mock_stage'))
|
|
||||||
spack.stage_path = new_stage
|
|
||||||
yield
|
|
||||||
spack.stage_path = stage_path
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def install_mockery(mock_stage, tmpdir, config, builtin_mock):
|
def install_mockery(tmpdir, config, builtin_mock):
|
||||||
"""Hooks a fake install directory, DB, and stage directory into Spack."""
|
"""Hooks a fake install directory, DB, and stage directory into Spack."""
|
||||||
layout = spack.store.layout
|
layout = spack.store.layout
|
||||||
db = spack.store.db
|
db = spack.store.db
|
||||||
|
@ -350,14 +400,13 @@ def fake_fn(self):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def mock_archive(mock_stage):
|
def mock_archive(tmpdir_factory):
|
||||||
"""Creates a very simple archive directory with a configure script and a
|
"""Creates a very simple archive directory with a configure script and a
|
||||||
makefile that installs to a prefix. Tars it up into an archive.
|
makefile that installs to a prefix. Tars it up into an archive.
|
||||||
"""
|
"""
|
||||||
tar = spack.util.executable.which('tar', required=True)
|
tar = spack.util.executable.which('tar', required=True)
|
||||||
stage = spack.stage.Stage('mock-archive-stage')
|
|
||||||
|
|
||||||
tmpdir = py.path.local(stage.path)
|
tmpdir = tmpdir_factory.mktemp('mock-archive-dir')
|
||||||
repo_name = 'mock-archive-repo'
|
repo_name = 'mock-archive-repo'
|
||||||
tmpdir.ensure(repo_name, dir=True)
|
tmpdir.ensure(repo_name, dir=True)
|
||||||
repodir = tmpdir.join(repo_name)
|
repodir = tmpdir.join(repo_name)
|
||||||
|
@ -392,17 +441,16 @@ def mock_archive(mock_stage):
|
||||||
url=('file://' + archive_file),
|
url=('file://' + archive_file),
|
||||||
archive_file=archive_file,
|
archive_file=archive_file,
|
||||||
path=str(repodir))
|
path=str(repodir))
|
||||||
stage.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def mock_git_repository(mock_stage):
|
def mock_git_repository(tmpdir_factory):
|
||||||
"""Creates a very simple git repository with two branches and
|
"""Creates a very simple git repository with two branches and
|
||||||
two commits.
|
two commits.
|
||||||
"""
|
"""
|
||||||
git = spack.util.executable.which('git', required=True)
|
git = spack.util.executable.which('git', required=True)
|
||||||
stage = spack.stage.Stage('mock-git-stage')
|
|
||||||
tmpdir = py.path.local(stage.path)
|
tmpdir = tmpdir_factory.mktemp('mock-git-repo-dir')
|
||||||
repo_name = 'mock-git-repo'
|
repo_name = 'mock-git-repo'
|
||||||
tmpdir.ensure(repo_name, dir=True)
|
tmpdir.ensure(repo_name, dir=True)
|
||||||
repodir = tmpdir.join(repo_name)
|
repodir = tmpdir.join(repo_name)
|
||||||
|
@ -449,7 +497,6 @@ def mock_git_repository(mock_stage):
|
||||||
r1_file = branch_file
|
r1_file = branch_file
|
||||||
|
|
||||||
Bunch = spack.util.pattern.Bunch
|
Bunch = spack.util.pattern.Bunch
|
||||||
|
|
||||||
checks = {
|
checks = {
|
||||||
'master': Bunch(
|
'master': Bunch(
|
||||||
revision='master', file=r0_file, args={'git': str(repodir)}
|
revision='master', file=r0_file, args={'git': str(repodir)}
|
||||||
|
@ -469,15 +516,14 @@ def mock_git_repository(mock_stage):
|
||||||
|
|
||||||
t = Bunch(checks=checks, url=url, hash=rev_hash, path=str(repodir))
|
t = Bunch(checks=checks, url=url, hash=rev_hash, path=str(repodir))
|
||||||
yield t
|
yield t
|
||||||
stage.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def mock_hg_repository(mock_stage):
|
def mock_hg_repository(tmpdir_factory):
|
||||||
"""Creates a very simple hg repository with two commits."""
|
"""Creates a very simple hg repository with two commits."""
|
||||||
hg = spack.util.executable.which('hg', required=True)
|
hg = spack.util.executable.which('hg', required=True)
|
||||||
stage = spack.stage.Stage('mock-hg-stage')
|
|
||||||
tmpdir = py.path.local(stage.path)
|
tmpdir = tmpdir_factory.mktemp('mock-hg-repo-dir')
|
||||||
repo_name = 'mock-hg-repo'
|
repo_name = 'mock-hg-repo'
|
||||||
tmpdir.ensure(repo_name, dir=True)
|
tmpdir.ensure(repo_name, dir=True)
|
||||||
repodir = tmpdir.join(repo_name)
|
repodir = tmpdir.join(repo_name)
|
||||||
|
@ -504,7 +550,6 @@ def mock_hg_repository(mock_stage):
|
||||||
r1 = get_rev()
|
r1 = get_rev()
|
||||||
|
|
||||||
Bunch = spack.util.pattern.Bunch
|
Bunch = spack.util.pattern.Bunch
|
||||||
|
|
||||||
checks = {
|
checks = {
|
||||||
'default': Bunch(
|
'default': Bunch(
|
||||||
revision=r1, file=r1_file, args={'hg': str(repodir)}
|
revision=r1, file=r1_file, args={'hg': str(repodir)}
|
||||||
|
@ -517,17 +562,15 @@ def mock_hg_repository(mock_stage):
|
||||||
}
|
}
|
||||||
t = Bunch(checks=checks, url=url, hash=get_rev, path=str(repodir))
|
t = Bunch(checks=checks, url=url, hash=get_rev, path=str(repodir))
|
||||||
yield t
|
yield t
|
||||||
stage.destroy()
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def mock_svn_repository(mock_stage):
|
def mock_svn_repository(tmpdir_factory):
|
||||||
"""Creates a very simple svn repository with two commits."""
|
"""Creates a very simple svn repository with two commits."""
|
||||||
svn = spack.util.executable.which('svn', required=True)
|
svn = spack.util.executable.which('svn', required=True)
|
||||||
svnadmin = spack.util.executable.which('svnadmin', required=True)
|
svnadmin = spack.util.executable.which('svnadmin', required=True)
|
||||||
stage = spack.stage.Stage('mock-svn-stage')
|
|
||||||
|
|
||||||
tmpdir = py.path.local(stage.path)
|
tmpdir = tmpdir_factory.mktemp('mock-svn-stage')
|
||||||
repo_name = 'mock-svn-repo'
|
repo_name = 'mock-svn-repo'
|
||||||
tmpdir.ensure(repo_name, dir=True)
|
tmpdir.ensure(repo_name, dir=True)
|
||||||
repodir = tmpdir.join(repo_name)
|
repodir = tmpdir.join(repo_name)
|
||||||
|
@ -563,26 +606,24 @@ def mock_svn_repository(mock_stage):
|
||||||
r0 = '1'
|
r0 = '1'
|
||||||
r1 = '2'
|
r1 = '2'
|
||||||
|
|
||||||
Bunch = spack.util.pattern.Bunch
|
Bunch = spack.util.pattern.Bunch
|
||||||
|
checks = {
|
||||||
|
'default': Bunch(
|
||||||
|
revision=r1, file=r1_file, args={'svn': url}),
|
||||||
|
'rev0': Bunch(
|
||||||
|
revision=r0, file=r0_file, args={
|
||||||
|
'svn': url, 'revision': r0})
|
||||||
|
}
|
||||||
|
|
||||||
checks = {
|
def get_rev():
|
||||||
'default': Bunch(
|
output = svn('info', output=str)
|
||||||
revision=r1, file=r1_file, args={'svn': url}),
|
assert "Revision" in output
|
||||||
'rev0': Bunch(
|
for line in output.split('\n'):
|
||||||
revision=r0, file=r0_file, args={
|
match = re.match(r'Revision: (\d+)', line)
|
||||||
'svn': url, 'revision': r0})
|
if match:
|
||||||
}
|
return match.group(1)
|
||||||
|
|
||||||
def get_rev():
|
|
||||||
output = svn('info', output=str)
|
|
||||||
assert "Revision" in output
|
|
||||||
for line in output.split('\n'):
|
|
||||||
match = re.match(r'Revision: (\d+)', line)
|
|
||||||
if match:
|
|
||||||
return match.group(1)
|
|
||||||
|
|
||||||
t = Bunch(checks=checks, url=url, hash=get_rev, path=str(repodir))
|
|
||||||
|
|
||||||
|
t = Bunch(checks=checks, url=url, hash=get_rev, path=str(repodir))
|
||||||
yield t
|
yield t
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -69,46 +69,49 @@ def __init__(self, wrapped_stage):
|
||||||
self.test_destroyed = False
|
self.test_destroyed = False
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
|
self.create()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, *exc):
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
return True
|
if exc_type is None:
|
||||||
|
self.destroy()
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
self.test_destroyed = True
|
self.test_destroyed = True
|
||||||
self.wrapped_stage.destroy()
|
self.wrapped_stage.destroy()
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
self.wrapped_stage.create()
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
return getattr(self.wrapped_stage, attr)
|
return getattr(self.wrapped_stage, attr)
|
||||||
|
|
||||||
|
|
||||||
def test_partial_install_delete_prefix_and_stage(install_mockery, mock_fetch):
|
def test_partial_install_delete_prefix_and_stage(install_mockery, mock_fetch):
|
||||||
spec = Spec('canfail')
|
spec = Spec('canfail').concretized()
|
||||||
spec.concretize()
|
|
||||||
pkg = spack.repo.get(spec)
|
pkg = spack.repo.get(spec)
|
||||||
remove_prefix = spack.package.Package.remove_prefix
|
remove_prefix = spack.package.Package.remove_prefix
|
||||||
instance_rm_prefix = pkg.remove_prefix
|
instance_rm_prefix = pkg.remove_prefix
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
pkg.succeed = False
|
||||||
spack.package.Package.remove_prefix = mock_remove_prefix
|
spack.package.Package.remove_prefix = mock_remove_prefix
|
||||||
with pytest.raises(MockInstallError):
|
with pytest.raises(MockInstallError):
|
||||||
pkg.do_install()
|
pkg.do_install()
|
||||||
assert os.path.isdir(pkg.prefix)
|
assert os.path.isdir(pkg.prefix)
|
||||||
rm_prefix_checker = RemovePrefixChecker(instance_rm_prefix)
|
rm_prefix_checker = RemovePrefixChecker(instance_rm_prefix)
|
||||||
spack.package.Package.remove_prefix = rm_prefix_checker.remove_prefix
|
spack.package.Package.remove_prefix = rm_prefix_checker.remove_prefix
|
||||||
setattr(pkg, 'succeed', True)
|
|
||||||
|
pkg.succeed = True
|
||||||
pkg.stage = MockStage(pkg.stage)
|
pkg.stage = MockStage(pkg.stage)
|
||||||
|
|
||||||
pkg.do_install(restage=True)
|
pkg.do_install(restage=True)
|
||||||
assert rm_prefix_checker.removed
|
assert rm_prefix_checker.removed
|
||||||
assert pkg.stage.test_destroyed
|
assert pkg.stage.test_destroyed
|
||||||
assert pkg.installed
|
assert pkg.installed
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
spack.package.Package.remove_prefix = remove_prefix
|
spack.package.Package.remove_prefix = remove_prefix
|
||||||
pkg._stage = None
|
|
||||||
try:
|
|
||||||
delattr(pkg, 'succeed')
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_dont_add_patches_to_installed_package(install_mockery, mock_fetch):
|
def test_dont_add_patches_to_installed_package(install_mockery, mock_fetch):
|
||||||
|
@ -141,53 +144,50 @@ def test_installed_dependency_request_conflicts(
|
||||||
dependent.concretize()
|
dependent.concretize()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_partial_install_keep_prefix(install_mockery, mock_fetch):
|
def test_partial_install_keep_prefix(install_mockery, mock_fetch):
|
||||||
spec = Spec('canfail')
|
spec = Spec('canfail').concretized()
|
||||||
spec.concretize()
|
|
||||||
pkg = spack.repo.get(spec)
|
pkg = spack.repo.get(spec)
|
||||||
|
|
||||||
# Normally the stage should start unset, but other tests set it
|
# Normally the stage should start unset, but other tests set it
|
||||||
pkg._stage = None
|
pkg._stage = None
|
||||||
remove_prefix = spack.package.Package.remove_prefix
|
remove_prefix = spack.package.Package.remove_prefix
|
||||||
try:
|
try:
|
||||||
# If remove_prefix is called at any point in this test, that is an
|
# If remove_prefix is called at any point in this test, that is an
|
||||||
# error
|
# error
|
||||||
|
pkg.succeed = False # make the build fail
|
||||||
spack.package.Package.remove_prefix = mock_remove_prefix
|
spack.package.Package.remove_prefix = mock_remove_prefix
|
||||||
with pytest.raises(spack.build_environment.ChildError):
|
with pytest.raises(spack.build_environment.ChildError):
|
||||||
pkg.do_install(keep_prefix=True)
|
pkg.do_install(keep_prefix=True)
|
||||||
assert os.path.exists(pkg.prefix)
|
assert os.path.exists(pkg.prefix)
|
||||||
setattr(pkg, 'succeed', True)
|
|
||||||
|
pkg.succeed = True # make the build succeed
|
||||||
pkg.stage = MockStage(pkg.stage)
|
pkg.stage = MockStage(pkg.stage)
|
||||||
pkg.do_install(keep_prefix=True)
|
pkg.do_install(keep_prefix=True)
|
||||||
assert pkg.installed
|
assert pkg.installed
|
||||||
assert not pkg.stage.test_destroyed
|
assert not pkg.stage.test_destroyed
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
spack.package.Package.remove_prefix = remove_prefix
|
spack.package.Package.remove_prefix = remove_prefix
|
||||||
pkg._stage = None
|
|
||||||
try:
|
|
||||||
delattr(pkg, 'succeed')
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_second_install_no_overwrite_first(install_mockery, mock_fetch):
|
def test_second_install_no_overwrite_first(install_mockery, mock_fetch):
|
||||||
spec = Spec('canfail')
|
spec = Spec('canfail').concretized()
|
||||||
spec.concretize()
|
|
||||||
pkg = spack.repo.get(spec)
|
pkg = spack.repo.get(spec)
|
||||||
remove_prefix = spack.package.Package.remove_prefix
|
remove_prefix = spack.package.Package.remove_prefix
|
||||||
try:
|
try:
|
||||||
spack.package.Package.remove_prefix = mock_remove_prefix
|
spack.package.Package.remove_prefix = mock_remove_prefix
|
||||||
setattr(pkg, 'succeed', True)
|
|
||||||
|
pkg.succeed = True
|
||||||
pkg.do_install()
|
pkg.do_install()
|
||||||
assert pkg.installed
|
assert pkg.installed
|
||||||
|
|
||||||
# If Package.install is called after this point, it will fail
|
# If Package.install is called after this point, it will fail
|
||||||
delattr(pkg, 'succeed')
|
pkg.succeed = False
|
||||||
pkg.do_install()
|
pkg.do_install()
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
spack.package.Package.remove_prefix = remove_prefix
|
spack.package.Package.remove_prefix = remove_prefix
|
||||||
try:
|
|
||||||
delattr(pkg, 'succeed')
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_store(install_mockery, mock_fetch):
|
def test_store(install_mockery, mock_fetch):
|
||||||
|
@ -196,9 +196,11 @@ def test_store(install_mockery, mock_fetch):
|
||||||
pkg.do_install()
|
pkg.do_install()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_failing_build(install_mockery, mock_fetch):
|
def test_failing_build(install_mockery, mock_fetch):
|
||||||
spec = Spec('failing-build').concretized()
|
spec = Spec('failing-build').concretized()
|
||||||
pkg = spec.package
|
pkg = spec.package
|
||||||
|
|
||||||
with pytest.raises(spack.build_environment.ChildError):
|
with pytest.raises(spack.build_environment.ChildError):
|
||||||
pkg.do_install()
|
pkg.do_install()
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,12 @@
|
||||||
import collections
|
import collections
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from llnl.util.filesystem import join_path, working_dir
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import spack
|
import spack
|
||||||
import spack.stage
|
import spack.stage
|
||||||
import spack.util.executable
|
import spack.util.executable
|
||||||
from llnl.util.filesystem import join_path, working_dir
|
|
||||||
from spack.stage import Stage
|
from spack.stage import Stage
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,24 +237,20 @@ def test_fetch(self, mock_archive):
|
||||||
check_destroy(stage, self.stage_name)
|
check_destroy(stage, self.stage_name)
|
||||||
|
|
||||||
def test_no_search_if_default_succeeds(
|
def test_no_search_if_default_succeeds(
|
||||||
self, mock_archive, failing_search_fn
|
self, mock_archive, failing_search_fn):
|
||||||
):
|
stage = Stage(mock_archive.url,
|
||||||
with Stage(
|
name=self.stage_name,
|
||||||
mock_archive.url,
|
search_fn=failing_search_fn)
|
||||||
name=self.stage_name,
|
with stage:
|
||||||
search_fn=failing_search_fn
|
|
||||||
) as stage:
|
|
||||||
stage.fetch()
|
stage.fetch()
|
||||||
check_destroy(stage, self.stage_name)
|
check_destroy(stage, self.stage_name)
|
||||||
|
|
||||||
def test_no_search_mirror_only(
|
def test_no_search_mirror_only(
|
||||||
self, failing_fetch_strategy, failing_search_fn
|
self, failing_fetch_strategy, failing_search_fn):
|
||||||
):
|
stage = Stage(failing_fetch_strategy,
|
||||||
with Stage(
|
name=self.stage_name,
|
||||||
failing_fetch_strategy,
|
search_fn=failing_search_fn)
|
||||||
name=self.stage_name,
|
with stage:
|
||||||
search_fn=failing_search_fn
|
|
||||||
) as stage:
|
|
||||||
try:
|
try:
|
||||||
stage.fetch(mirror_only=True)
|
stage.fetch(mirror_only=True)
|
||||||
except spack.fetch_strategy.FetchError:
|
except spack.fetch_strategy.FetchError:
|
||||||
|
@ -261,11 +258,10 @@ def test_no_search_mirror_only(
|
||||||
check_destroy(stage, self.stage_name)
|
check_destroy(stage, self.stage_name)
|
||||||
|
|
||||||
def test_search_if_default_fails(self, failing_fetch_strategy, search_fn):
|
def test_search_if_default_fails(self, failing_fetch_strategy, search_fn):
|
||||||
with Stage(
|
stage = Stage(failing_fetch_strategy,
|
||||||
failing_fetch_strategy,
|
name=self.stage_name,
|
||||||
name=self.stage_name,
|
search_fn=search_fn)
|
||||||
search_fn=search_fn
|
with stage:
|
||||||
) as stage:
|
|
||||||
try:
|
try:
|
||||||
stage.fetch(mirror_only=False)
|
stage.fetch(mirror_only=False)
|
||||||
except spack.fetch_strategy.FetchError:
|
except spack.fetch_strategy.FetchError:
|
||||||
|
@ -303,40 +299,43 @@ def test_restage(self, mock_archive):
|
||||||
check_destroy(stage, self.stage_name)
|
check_destroy(stage, self.stage_name)
|
||||||
|
|
||||||
def test_no_keep_without_exceptions(self, mock_archive):
|
def test_no_keep_without_exceptions(self, mock_archive):
|
||||||
with Stage(
|
stage = Stage(mock_archive.url, name=self.stage_name, keep=False)
|
||||||
mock_archive.url, name=self.stage_name, keep=False
|
with stage:
|
||||||
) as stage:
|
|
||||||
pass
|
pass
|
||||||
check_destroy(stage, self.stage_name)
|
check_destroy(stage, self.stage_name)
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_keep_without_exceptions(self, mock_archive):
|
def test_keep_without_exceptions(self, mock_archive):
|
||||||
with Stage(
|
stage = Stage(mock_archive.url, name=self.stage_name, keep=True)
|
||||||
mock_archive.url, name=self.stage_name, keep=True
|
with stage:
|
||||||
) as stage:
|
|
||||||
pass
|
pass
|
||||||
path = get_stage_path(stage, self.stage_name)
|
path = get_stage_path(stage, self.stage_name)
|
||||||
assert os.path.isdir(path)
|
assert os.path.isdir(path)
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_no_keep_with_exceptions(self, mock_archive):
|
def test_no_keep_with_exceptions(self, mock_archive):
|
||||||
class ThisMustFailHere(Exception):
|
class ThisMustFailHere(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
stage = Stage(mock_archive.url, name=self.stage_name, keep=False)
|
||||||
try:
|
try:
|
||||||
with Stage(
|
with stage:
|
||||||
mock_archive.url, name=self.stage_name, keep=False
|
|
||||||
) as stage:
|
|
||||||
raise ThisMustFailHere()
|
raise ThisMustFailHere()
|
||||||
|
|
||||||
except ThisMustFailHere:
|
except ThisMustFailHere:
|
||||||
path = get_stage_path(stage, self.stage_name)
|
path = get_stage_path(stage, self.stage_name)
|
||||||
assert os.path.isdir(path)
|
assert os.path.isdir(path)
|
||||||
|
|
||||||
|
@pytest.mark.disable_clean_stage_check
|
||||||
def test_keep_exceptions(self, mock_archive):
|
def test_keep_exceptions(self, mock_archive):
|
||||||
class ThisMustFailHere(Exception):
|
class ThisMustFailHere(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
stage = Stage(mock_archive.url, name=self.stage_name, keep=True)
|
||||||
try:
|
try:
|
||||||
with Stage(
|
with stage:
|
||||||
mock_archive.url, name=self.stage_name, keep=True
|
|
||||||
) as stage:
|
|
||||||
raise ThisMustFailHere()
|
raise ThisMustFailHere()
|
||||||
|
|
||||||
except ThisMustFailHere:
|
except ThisMustFailHere:
|
||||||
path = get_stage_path(stage, self.stage_name)
|
path = get_stage_path(stage, self.stage_name)
|
||||||
assert os.path.isdir(path)
|
assert os.path.isdir(path)
|
||||||
|
|
|
@ -33,11 +33,9 @@ class Canfail(Package):
|
||||||
|
|
||||||
version('1.0', '0123456789abcdef0123456789abcdef')
|
version('1.0', '0123456789abcdef0123456789abcdef')
|
||||||
|
|
||||||
|
succeed = False
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
try:
|
if not self.succeed:
|
||||||
succeed = getattr(self, 'succeed')
|
raise InstallError("'succeed' was false")
|
||||||
if not succeed:
|
touch(join_path(prefix, 'an_installation_file'))
|
||||||
raise InstallError("'succeed' was false")
|
|
||||||
touch(join_path(prefix, 'an_installation_file'))
|
|
||||||
except AttributeError:
|
|
||||||
raise InstallError("'succeed' attribute was not set")
|
|
||||||
|
|
Loading…
Reference in a new issue