Refactor unit-tests in test/architecture.py (#25848)
Modifications: - Export platforms from spack.platforms directly, so that client modules don't have to import submodules - Use only plain imports in test/architecture.py - Parametrized test in test/architecture.py and put most of the setup/teardown in fixtures
This commit is contained in:
parent
d8b95a496c
commit
5fddd48f80
@ -30,6 +30,7 @@
|
|||||||
import spack.main
|
import spack.main
|
||||||
import spack.modules
|
import spack.modules
|
||||||
import spack.paths
|
import spack.paths
|
||||||
|
import spack.platforms
|
||||||
import spack.repo
|
import spack.repo
|
||||||
import spack.spec
|
import spack.spec
|
||||||
import spack.store
|
import spack.store
|
||||||
@ -178,9 +179,6 @@ def __init__(self, conf):
|
|||||||
self.url = conf['info']['url']
|
self.url = conf['info']['url']
|
||||||
|
|
||||||
def try_import(self, module, abstract_spec_str):
|
def try_import(self, module, abstract_spec_str):
|
||||||
# This import is local since it is needed only on Cray
|
|
||||||
import spack.platforms.linux
|
|
||||||
|
|
||||||
if _try_import_from_store(module, abstract_spec_str):
|
if _try_import_from_store(module, abstract_spec_str):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -192,7 +190,7 @@ def try_import(self, module, abstract_spec_str):
|
|||||||
# On Cray we want to use Linux binaries if available from mirrors
|
# On Cray we want to use Linux binaries if available from mirrors
|
||||||
bincache_platform = spack.architecture.real_platform()
|
bincache_platform = spack.architecture.real_platform()
|
||||||
if str(bincache_platform) == 'cray':
|
if str(bincache_platform) == 'cray':
|
||||||
bincache_platform = spack.platforms.linux.Linux()
|
bincache_platform = spack.platforms.Linux()
|
||||||
with spack.architecture.use_platform(bincache_platform):
|
with spack.architecture.use_platform(bincache_platform):
|
||||||
abstract_spec = spack.spec.Spec(
|
abstract_spec = spack.spec.Spec(
|
||||||
abstract_spec_str + ' ^' + spec_for_current_python()
|
abstract_spec_str + ' ^' + spec_for_current_python()
|
||||||
|
@ -2,3 +2,14 @@
|
|||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
from .cray import Cray
|
||||||
|
from .darwin import Darwin
|
||||||
|
from .linux import Linux
|
||||||
|
from .test import Test
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'Cray',
|
||||||
|
'Darwin',
|
||||||
|
'Linux',
|
||||||
|
'Test'
|
||||||
|
]
|
||||||
|
@ -2,141 +2,112 @@
|
|||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
""" Test checks if the architecture class is created correctly and also that
|
|
||||||
the functions are looking for the correct architecture name
|
|
||||||
"""
|
|
||||||
import itertools
|
|
||||||
import os
|
import os
|
||||||
import platform as py_platform
|
import platform
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import spack.architecture
|
import spack.architecture
|
||||||
import spack.concretize
|
import spack.concretize
|
||||||
from spack.platforms.cray import Cray
|
import spack.platforms
|
||||||
from spack.platforms.darwin import Darwin
|
import spack.spec
|
||||||
from spack.platforms.linux import Linux
|
|
||||||
from spack.spec import Spec
|
|
||||||
|
|
||||||
|
|
||||||
def test_dict_functions_for_architecture():
|
@pytest.fixture
|
||||||
|
def sample_arch():
|
||||||
|
"""Sample test architecture"""
|
||||||
arch = spack.architecture.Arch()
|
arch = spack.architecture.Arch()
|
||||||
arch.platform = spack.architecture.platform()
|
arch.platform = spack.architecture.platform()
|
||||||
arch.os = arch.platform.operating_system('default_os')
|
arch.os = arch.platform.operating_system('default_os')
|
||||||
arch.target = arch.platform.target('default_target')
|
arch.target = arch.platform.target('default_target')
|
||||||
|
return arch
|
||||||
new_arch = spack.architecture.Arch.from_dict(arch.to_dict())
|
|
||||||
|
|
||||||
assert arch == new_arch
|
|
||||||
assert isinstance(arch, spack.architecture.Arch)
|
|
||||||
assert isinstance(arch.platform, spack.architecture.Platform)
|
|
||||||
assert isinstance(arch.os, spack.architecture.OperatingSystem)
|
|
||||||
assert isinstance(arch.target, spack.architecture.Target)
|
|
||||||
assert isinstance(new_arch, spack.architecture.Arch)
|
|
||||||
assert isinstance(new_arch.platform, spack.architecture.Platform)
|
|
||||||
assert isinstance(new_arch.os, spack.architecture.OperatingSystem)
|
|
||||||
assert isinstance(new_arch.target, spack.architecture.Target)
|
|
||||||
|
|
||||||
|
|
||||||
def test_platform():
|
@pytest.fixture
|
||||||
output_platform_class = spack.architecture.real_platform()
|
def current_host_platform():
|
||||||
|
"""Return the platform of the current host as detected by the
|
||||||
|
'platform' stdlib package.
|
||||||
|
"""
|
||||||
if os.path.exists('/opt/cray/pe'):
|
if os.path.exists('/opt/cray/pe'):
|
||||||
my_platform_class = Cray()
|
current_platform = spack.platforms.Cray()
|
||||||
elif 'Linux' in py_platform.system():
|
elif 'Linux' in platform.system():
|
||||||
my_platform_class = Linux()
|
current_platform = spack.platforms.Linux()
|
||||||
elif 'Darwin' in py_platform.system():
|
elif 'Darwin' in platform.system():
|
||||||
my_platform_class = Darwin()
|
current_platform = spack.platforms.Darwin()
|
||||||
|
return current_platform
|
||||||
assert str(output_platform_class) == str(my_platform_class)
|
|
||||||
|
|
||||||
|
|
||||||
def test_boolness():
|
# Valid keywords for os=xxx or target=xxx
|
||||||
|
valid_keywords = ["fe", "be", "frontend", "backend"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
params=([x for x in spack.platforms.Test().targets]
|
||||||
|
+ valid_keywords + ['default_target'])
|
||||||
|
)
|
||||||
|
def target_str(request):
|
||||||
|
"""All the possible strings that can be used for targets"""
|
||||||
|
return str(request.param)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(
|
||||||
|
params=([x for x in spack.platforms.Test().operating_sys]
|
||||||
|
+ valid_keywords + ['default_os'])
|
||||||
|
)
|
||||||
|
def os_str(request):
|
||||||
|
"""All the possible strings that can be used for operating systems"""
|
||||||
|
return str(request.param)
|
||||||
|
|
||||||
|
|
||||||
|
def test_dict_round_trip(sample_arch):
|
||||||
|
"""Check that a round trip through dict return an equivalent architecture"""
|
||||||
|
sample_arch_copy = spack.architecture.Arch.from_dict(sample_arch.to_dict())
|
||||||
|
|
||||||
|
assert sample_arch == sample_arch_copy
|
||||||
|
for current_arch in (sample_arch, sample_arch_copy):
|
||||||
|
assert isinstance(current_arch, spack.architecture.Arch)
|
||||||
|
assert isinstance(current_arch.platform, spack.architecture.Platform)
|
||||||
|
assert isinstance(current_arch.os, spack.architecture.OperatingSystem)
|
||||||
|
assert isinstance(current_arch.target, spack.architecture.Target)
|
||||||
|
|
||||||
|
|
||||||
|
def test_platform(current_host_platform):
|
||||||
|
"""Check that current host detection return the correct platform"""
|
||||||
|
detected_platform = spack.architecture.real_platform()
|
||||||
|
assert str(detected_platform) == str(current_host_platform)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('attribute_name,expected', [
|
||||||
# Make sure architecture reports that it's False when nothing's set.
|
# Make sure architecture reports that it's False when nothing's set.
|
||||||
|
(None, False),
|
||||||
|
# ... and it reports True otherwise
|
||||||
|
('platform', True),
|
||||||
|
('os', True),
|
||||||
|
('target', True)
|
||||||
|
])
|
||||||
|
def test_boolness(sample_arch, attribute_name, expected):
|
||||||
|
"""Boolean checks on an architecture object"""
|
||||||
arch = spack.architecture.Arch()
|
arch = spack.architecture.Arch()
|
||||||
assert not arch
|
if attribute_name:
|
||||||
|
setattr(arch, attribute_name, getattr(sample_arch, attribute_name))
|
||||||
|
|
||||||
# Dummy architecture parts
|
assert bool(arch) is expected
|
||||||
plat = spack.architecture.platform()
|
|
||||||
plat_os = plat.operating_system('default_os')
|
|
||||||
plat_target = plat.target('default_target')
|
|
||||||
|
|
||||||
# Make sure architecture reports that it's True when anything is set.
|
|
||||||
arch = spack.architecture.Arch()
|
|
||||||
arch.platform = plat
|
|
||||||
assert arch
|
|
||||||
|
|
||||||
arch = spack.architecture.Arch()
|
|
||||||
arch.os = plat_os
|
|
||||||
assert arch
|
|
||||||
|
|
||||||
arch = spack.architecture.Arch()
|
|
||||||
arch.target = plat_target
|
|
||||||
assert arch
|
|
||||||
|
|
||||||
|
|
||||||
def test_user_front_end_input(config):
|
def test_user_input_combination(config, target_str, os_str):
|
||||||
"""Test when user inputs just frontend that both the frontend target
|
"""Test for all the valid user input combinations that both the target and
|
||||||
and frontend operating system match
|
the operating system match.
|
||||||
"""
|
"""
|
||||||
platform = spack.architecture.platform()
|
platform = spack.platforms.Test()
|
||||||
frontend_os = str(platform.operating_system('frontend'))
|
spec_str = "libelf"
|
||||||
frontend_target = platform.target('frontend')
|
if os_str != "default_os":
|
||||||
|
spec_str += " os={0}".format(os_str)
|
||||||
|
if target_str != "default_target":
|
||||||
|
spec_str += " target={0}".format(target_str)
|
||||||
|
spec = spack.spec.Spec(spec_str).concretized()
|
||||||
|
|
||||||
frontend_spec = Spec('libelf os=frontend target=frontend')
|
assert spec.architecture.os == str(platform.operating_system(os_str))
|
||||||
frontend_spec.concretize()
|
assert spec.architecture.target == platform.target(target_str)
|
||||||
|
|
||||||
assert frontend_os == frontend_spec.architecture.os
|
|
||||||
assert frontend_target == frontend_spec.architecture.target
|
|
||||||
|
|
||||||
|
|
||||||
def test_user_back_end_input(config):
|
|
||||||
"""Test when user inputs backend that both the backend target and
|
|
||||||
backend operating system match
|
|
||||||
"""
|
|
||||||
platform = spack.architecture.platform()
|
|
||||||
backend_os = str(platform.operating_system("backend"))
|
|
||||||
backend_target = platform.target("backend")
|
|
||||||
|
|
||||||
backend_spec = Spec("libelf os=backend target=backend")
|
|
||||||
backend_spec.concretize()
|
|
||||||
|
|
||||||
assert backend_os == backend_spec.architecture.os
|
|
||||||
assert backend_target == backend_spec.architecture.target
|
|
||||||
|
|
||||||
|
|
||||||
def test_user_defaults(config):
|
|
||||||
platform = spack.architecture.platform()
|
|
||||||
default_os = str(platform.operating_system("default_os"))
|
|
||||||
default_target = platform.target("default_target")
|
|
||||||
|
|
||||||
default_spec = Spec("libelf") # default is no args
|
|
||||||
default_spec.concretize()
|
|
||||||
|
|
||||||
assert default_os == default_spec.architecture.os
|
|
||||||
assert default_target == default_spec.architecture.target
|
|
||||||
|
|
||||||
|
|
||||||
def test_user_input_combination(config):
|
|
||||||
valid_keywords = ["fe", "be", "frontend", "backend"]
|
|
||||||
|
|
||||||
possible_targets = ([x for x in spack.architecture.platform().targets]
|
|
||||||
+ valid_keywords)
|
|
||||||
|
|
||||||
possible_os = ([x for x in spack.architecture.platform().operating_sys]
|
|
||||||
+ valid_keywords)
|
|
||||||
|
|
||||||
for target, operating_system in itertools.product(
|
|
||||||
possible_targets, possible_os
|
|
||||||
):
|
|
||||||
platform = spack.architecture.platform()
|
|
||||||
spec_str = "libelf os={0} target={1}".format(operating_system, target)
|
|
||||||
spec = Spec(spec_str)
|
|
||||||
spec.concretize()
|
|
||||||
assert spec.architecture.os == str(
|
|
||||||
platform.operating_system(operating_system)
|
|
||||||
)
|
|
||||||
assert spec.architecture.target == platform.target(target)
|
|
||||||
|
|
||||||
|
|
||||||
def test_operating_system_conversion_to_dict():
|
def test_operating_system_conversion_to_dict():
|
||||||
@ -234,16 +205,15 @@ def test_satisfy_strict_constraint_when_not_concrete(
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('root_target_range,dep_target_range,result', [
|
@pytest.mark.parametrize('root_target_range,dep_target_range,result', [
|
||||||
(('x86_64:nocona', 'x86_64:core2', 'nocona')), # pref not in intersection
|
('x86_64:nocona', 'x86_64:core2', 'nocona'), # pref not in intersection
|
||||||
(('x86_64:core2', 'x86_64:nocona', 'nocona')),
|
('x86_64:core2', 'x86_64:nocona', 'nocona'),
|
||||||
(('x86_64:haswell', 'x86_64:mic_knl', 'core2')), # pref in intersection
|
('x86_64:haswell', 'x86_64:mic_knl', 'core2'), # pref in intersection
|
||||||
(('ivybridge', 'nocona:skylake', 'ivybridge')), # one side concrete
|
('ivybridge', 'nocona:skylake', 'ivybridge'), # one side concrete
|
||||||
(('haswell:icelake', 'broadwell', 'broadwell')),
|
('haswell:icelake', 'broadwell', 'broadwell'),
|
||||||
# multiple ranges in lists with multiple overlaps
|
# multiple ranges in lists with multiple overlaps
|
||||||
(('x86_64:nocona,haswell:broadwell', 'nocona:haswell,skylake:',
|
('x86_64:nocona,haswell:broadwell', 'nocona:haswell,skylake:', 'nocona'),
|
||||||
'nocona')),
|
|
||||||
# lists with concrete targets, lists compared to ranges
|
# lists with concrete targets, lists compared to ranges
|
||||||
(('x86_64,haswell', 'core2:broadwell', 'haswell'))
|
('x86_64,haswell', 'core2:broadwell', 'haswell')
|
||||||
])
|
])
|
||||||
@pytest.mark.usefixtures('mock_packages', 'config')
|
@pytest.mark.usefixtures('mock_packages', 'config')
|
||||||
def test_concretize_target_ranges(
|
def test_concretize_target_ranges(
|
||||||
@ -251,8 +221,9 @@ def test_concretize_target_ranges(
|
|||||||
):
|
):
|
||||||
# use foobar=bar to make the problem simpler for the old concretizer
|
# use foobar=bar to make the problem simpler for the old concretizer
|
||||||
# the new concretizer should not need that help
|
# the new concretizer should not need that help
|
||||||
spec = Spec('a %%gcc@10 foobar=bar target=%s ^b target=%s' %
|
spec_str = ('a %%gcc@10 foobar=bar target=%s ^b target=%s' %
|
||||||
(root_target_range, dep_target_range))
|
(root_target_range, dep_target_range))
|
||||||
|
spec = spack.spec.Spec(spec_str)
|
||||||
with spack.concretize.disable_compiler_existence_check():
|
with spack.concretize.disable_compiler_existence_check():
|
||||||
spec.concretize()
|
spec.concretize()
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import spack.compilers
|
import spack.compilers
|
||||||
import spack.concretize
|
import spack.concretize
|
||||||
import spack.error
|
import spack.error
|
||||||
import spack.platforms.test
|
import spack.platforms
|
||||||
import spack.repo
|
import spack.repo
|
||||||
from spack.concretize import find_spec
|
from spack.concretize import find_spec
|
||||||
from spack.spec import Spec
|
from spack.spec import Spec
|
||||||
@ -101,8 +101,8 @@ def current_host(request, monkeypatch):
|
|||||||
# this function is memoized, so clear its state for testing
|
# this function is memoized, so clear its state for testing
|
||||||
spack.architecture.get_platform.cache.clear()
|
spack.architecture.get_platform.cache.clear()
|
||||||
|
|
||||||
monkeypatch.setattr(spack.platforms.test.Test, 'default', cpu)
|
monkeypatch.setattr(spack.platforms.Test, 'default', cpu)
|
||||||
monkeypatch.setattr(spack.platforms.test.Test, 'front_end', cpu)
|
monkeypatch.setattr(spack.platforms.Test, 'front_end', cpu)
|
||||||
if not is_preference:
|
if not is_preference:
|
||||||
monkeypatch.setattr(archspec.cpu, 'host', lambda: target)
|
monkeypatch.setattr(archspec.cpu, 'host', lambda: target)
|
||||||
yield target
|
yield target
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
import spack.package
|
import spack.package
|
||||||
import spack.package_prefs
|
import spack.package_prefs
|
||||||
import spack.paths
|
import spack.paths
|
||||||
import spack.platforms.test
|
import spack.platforms
|
||||||
import spack.repo
|
import spack.repo
|
||||||
import spack.stage
|
import spack.stage
|
||||||
import spack.store
|
import spack.store
|
||||||
@ -345,7 +345,7 @@ def _skip_if_missing_executables(request):
|
|||||||
|
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def test_platform():
|
def test_platform():
|
||||||
return spack.platforms.test.Test()
|
return spack.platforms.Test()
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True, scope='session')
|
@pytest.fixture(autouse=True, scope='session')
|
||||||
|
Loading…
Reference in New Issue
Block a user