Speed-up unit tests by caching default mock concretization (#33755)
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							5f8511311c
						
					
				
				
					commit
					022a2d2eaf
				
			@@ -17,7 +17,7 @@
 | 
			
		||||
import spack.target
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
@pytest.fixture(scope="module")
 | 
			
		||||
def current_host_platform():
 | 
			
		||||
    """Return the platform of the current host as detected by the
 | 
			
		||||
    'platform' stdlib package.
 | 
			
		||||
@@ -34,23 +34,23 @@ def current_host_platform():
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Valid keywords for os=xxx or target=xxx
 | 
			
		||||
valid_keywords = ["fe", "be", "frontend", "backend"]
 | 
			
		||||
VALID_KEYWORDS = ["fe", "be", "frontend", "backend"]
 | 
			
		||||
 | 
			
		||||
TEST_PLATFORM = spack.platforms.Test()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(
 | 
			
		||||
    params=([x for x in spack.platforms.Test().targets] + valid_keywords + ["default_target"])
 | 
			
		||||
)
 | 
			
		||||
@pytest.fixture(params=([str(x) for x in TEST_PLATFORM.targets] + VALID_KEYWORDS), scope="module")
 | 
			
		||||
def target_str(request):
 | 
			
		||||
    """All the possible strings that can be used for targets"""
 | 
			
		||||
    return str(request.param)
 | 
			
		||||
    return request.param
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(
 | 
			
		||||
    params=([x for x in spack.platforms.Test().operating_sys] + valid_keywords + ["default_os"])
 | 
			
		||||
    params=([str(x) for x in TEST_PLATFORM.operating_sys] + VALID_KEYWORDS), scope="module"
 | 
			
		||||
)
 | 
			
		||||
def os_str(request):
 | 
			
		||||
    """All the possible strings that can be used for operating systems"""
 | 
			
		||||
    return str(request.param)
 | 
			
		||||
    return request.param
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_platform(current_host_platform):
 | 
			
		||||
@@ -64,16 +64,19 @@ def test_user_input_combination(config, target_str, os_str):
 | 
			
		||||
    """Test for all the valid user input combinations that both the target and
 | 
			
		||||
    the operating system match.
 | 
			
		||||
    """
 | 
			
		||||
    platform = spack.platforms.Test()
 | 
			
		||||
    spec_str = "libelf"
 | 
			
		||||
    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()
 | 
			
		||||
    spec_str = "libelf os={} target={}".format(os_str, target_str)
 | 
			
		||||
    spec = spack.spec.Spec(spec_str)
 | 
			
		||||
    assert spec.architecture.os == str(TEST_PLATFORM.operating_system(os_str))
 | 
			
		||||
    assert spec.architecture.target == TEST_PLATFORM.target(target_str)
 | 
			
		||||
 | 
			
		||||
    assert spec.architecture.os == str(platform.operating_system(os_str))
 | 
			
		||||
    assert spec.architecture.target == platform.target(target_str)
 | 
			
		||||
 | 
			
		||||
def test_default_os_and_target(config):
 | 
			
		||||
    """Test that is we don't specify `os=` or `target=` we get the default values
 | 
			
		||||
    after concretization.
 | 
			
		||||
    """
 | 
			
		||||
    spec = spack.spec.Spec("libelf").concretized()
 | 
			
		||||
    assert spec.architecture.os == str(TEST_PLATFORM.operating_system("default_os"))
 | 
			
		||||
    assert spec.architecture.target == TEST_PLATFORM.target("default_target")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_operating_system_conversion_to_dict():
 | 
			
		||||
 
 | 
			
		||||
@@ -27,9 +27,9 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture()
 | 
			
		||||
def concretize_and_setup():
 | 
			
		||||
def concretize_and_setup(default_mock_concretization):
 | 
			
		||||
    def _func(spec_str):
 | 
			
		||||
        s = Spec("mpich").concretized()
 | 
			
		||||
        s = default_mock_concretization(spec_str)
 | 
			
		||||
        setup_package(s.package, False)
 | 
			
		||||
        return s
 | 
			
		||||
 | 
			
		||||
@@ -95,8 +95,8 @@ def test_negative_ninja_check(self, input_dir, test_dir, concretize_and_setup):
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures("config", "mock_packages")
 | 
			
		||||
class TestAutotoolsPackage(object):
 | 
			
		||||
    def test_with_or_without(self):
 | 
			
		||||
        s = Spec("a").concretized()
 | 
			
		||||
    def test_with_or_without(self, default_mock_concretization):
 | 
			
		||||
        s = default_mock_concretization("a")
 | 
			
		||||
        options = s.package.with_or_without("foo")
 | 
			
		||||
 | 
			
		||||
        # Ensure that values that are not representing a feature
 | 
			
		||||
@@ -127,8 +127,8 @@ def activate(value):
 | 
			
		||||
        options = s.package.with_or_without("lorem-ipsum", variant="lorem_ipsum")
 | 
			
		||||
        assert "--without-lorem-ipsum" in options
 | 
			
		||||
 | 
			
		||||
    def test_none_is_allowed(self):
 | 
			
		||||
        s = Spec("a foo=none").concretized()
 | 
			
		||||
    def test_none_is_allowed(self, default_mock_concretization):
 | 
			
		||||
        s = default_mock_concretization("a foo=none")
 | 
			
		||||
        options = s.package.with_or_without("foo")
 | 
			
		||||
 | 
			
		||||
        # Ensure that values that are not representing a feature
 | 
			
		||||
@@ -138,9 +138,11 @@ def test_none_is_allowed(self):
 | 
			
		||||
        assert "--without-baz" in options
 | 
			
		||||
        assert "--no-fee" in options
 | 
			
		||||
 | 
			
		||||
    def test_libtool_archive_files_are_deleted_by_default(self, mutable_database):
 | 
			
		||||
    def test_libtool_archive_files_are_deleted_by_default(
 | 
			
		||||
        self, default_mock_concretization, mutable_database
 | 
			
		||||
    ):
 | 
			
		||||
        # Install a package that creates a mock libtool archive
 | 
			
		||||
        s = Spec("libtool-deletion").concretized()
 | 
			
		||||
        s = default_mock_concretization("libtool-deletion")
 | 
			
		||||
        s.package.do_install(explicit=True)
 | 
			
		||||
 | 
			
		||||
        # Assert the libtool archive is not there and we have
 | 
			
		||||
@@ -151,24 +153,25 @@ def test_libtool_archive_files_are_deleted_by_default(self, mutable_database):
 | 
			
		||||
        assert libtool_deletion_log
 | 
			
		||||
 | 
			
		||||
    def test_libtool_archive_files_might_be_installed_on_demand(
 | 
			
		||||
        self, mutable_database, monkeypatch
 | 
			
		||||
        self, mutable_database, monkeypatch, default_mock_concretization
 | 
			
		||||
    ):
 | 
			
		||||
        # Install a package that creates a mock libtool archive,
 | 
			
		||||
        # patch its package to preserve the installation
 | 
			
		||||
        s = Spec("libtool-deletion").concretized()
 | 
			
		||||
        s = default_mock_concretization("libtool-deletion")
 | 
			
		||||
        monkeypatch.setattr(type(s.package.builder), "install_libtool_archives", True)
 | 
			
		||||
        s.package.do_install(explicit=True)
 | 
			
		||||
 | 
			
		||||
        # Assert libtool archives are installed
 | 
			
		||||
        assert os.path.exists(s.package.builder.libtool_archive_file)
 | 
			
		||||
 | 
			
		||||
    def test_autotools_gnuconfig_replacement(self, mutable_database):
 | 
			
		||||
    def test_autotools_gnuconfig_replacement(self, default_mock_concretization, mutable_database):
 | 
			
		||||
        """
 | 
			
		||||
        Tests whether only broken config.sub and config.guess are replaced with
 | 
			
		||||
        files from working alternatives from the gnuconfig package.
 | 
			
		||||
        """
 | 
			
		||||
        s = Spec("autotools-config-replacement +patch_config_files +gnuconfig")
 | 
			
		||||
        s.concretize()
 | 
			
		||||
        s = default_mock_concretization(
 | 
			
		||||
            "autotools-config-replacement +patch_config_files +gnuconfig"
 | 
			
		||||
        )
 | 
			
		||||
        s.package.do_install()
 | 
			
		||||
 | 
			
		||||
        with open(os.path.join(s.prefix.broken, "config.sub")) as f:
 | 
			
		||||
@@ -183,12 +186,15 @@ def test_autotools_gnuconfig_replacement(self, mutable_database):
 | 
			
		||||
        with open(os.path.join(s.prefix.working, "config.guess")) as f:
 | 
			
		||||
            assert "gnuconfig version of config.guess" not in f.read()
 | 
			
		||||
 | 
			
		||||
    def test_autotools_gnuconfig_replacement_disabled(self, mutable_database):
 | 
			
		||||
    def test_autotools_gnuconfig_replacement_disabled(
 | 
			
		||||
        self, default_mock_concretization, mutable_database
 | 
			
		||||
    ):
 | 
			
		||||
        """
 | 
			
		||||
        Tests whether disabling patch_config_files
 | 
			
		||||
        """
 | 
			
		||||
        s = Spec("autotools-config-replacement ~patch_config_files +gnuconfig")
 | 
			
		||||
        s.concretize()
 | 
			
		||||
        s = default_mock_concretization(
 | 
			
		||||
            "autotools-config-replacement ~patch_config_files +gnuconfig"
 | 
			
		||||
        )
 | 
			
		||||
        s.package.do_install()
 | 
			
		||||
 | 
			
		||||
        with open(os.path.join(s.prefix.broken, "config.sub")) as f:
 | 
			
		||||
@@ -252,29 +258,29 @@ def test_broken_external_gnuconfig(self, mutable_database, tmpdir):
 | 
			
		||||
 | 
			
		||||
@pytest.mark.usefixtures("config", "mock_packages")
 | 
			
		||||
class TestCMakePackage(object):
 | 
			
		||||
    def test_cmake_std_args(self):
 | 
			
		||||
    def test_cmake_std_args(self, default_mock_concretization):
 | 
			
		||||
        # Call the function on a CMakePackage instance
 | 
			
		||||
        s = Spec("cmake-client").concretized()
 | 
			
		||||
        s = default_mock_concretization("cmake-client")
 | 
			
		||||
        expected = spack.build_systems.cmake.CMakeBuilder.std_args(s.package)
 | 
			
		||||
        assert s.package.builder.std_cmake_args == expected
 | 
			
		||||
 | 
			
		||||
        # Call it on another kind of package
 | 
			
		||||
        s = Spec("mpich").concretized()
 | 
			
		||||
        s = default_mock_concretization("mpich")
 | 
			
		||||
        assert spack.build_systems.cmake.CMakeBuilder.std_args(s.package)
 | 
			
		||||
 | 
			
		||||
    def test_cmake_bad_generator(self, monkeypatch):
 | 
			
		||||
        s = Spec("cmake-client").concretized()
 | 
			
		||||
    def test_cmake_bad_generator(self, monkeypatch, default_mock_concretization):
 | 
			
		||||
        s = default_mock_concretization("cmake-client")
 | 
			
		||||
        monkeypatch.setattr(type(s.package), "generator", "Yellow Sticky Notes", raising=False)
 | 
			
		||||
        with pytest.raises(spack.package_base.InstallError):
 | 
			
		||||
            s.package.builder.std_cmake_args
 | 
			
		||||
 | 
			
		||||
    def test_cmake_secondary_generator(config, mock_packages):
 | 
			
		||||
        s = Spec("cmake-client").concretized()
 | 
			
		||||
    def test_cmake_secondary_generator(self, default_mock_concretization):
 | 
			
		||||
        s = default_mock_concretization("cmake-client")
 | 
			
		||||
        s.package.generator = "CodeBlocks - Unix Makefiles"
 | 
			
		||||
        assert s.package.builder.std_cmake_args
 | 
			
		||||
 | 
			
		||||
    def test_define(self):
 | 
			
		||||
        s = Spec("cmake-client").concretized()
 | 
			
		||||
    def test_define(self, default_mock_concretization):
 | 
			
		||||
        s = default_mock_concretization("cmake-client")
 | 
			
		||||
 | 
			
		||||
        define = s.package.define
 | 
			
		||||
        for cls in (list, tuple):
 | 
			
		||||
@@ -324,8 +330,8 @@ class TestDownloadMixins(object):
 | 
			
		||||
            ),
 | 
			
		||||
        ],
 | 
			
		||||
    )
 | 
			
		||||
    def test_attributes_defined(self, spec_str, expected_url):
 | 
			
		||||
        s = Spec(spec_str).concretized()
 | 
			
		||||
    def test_attributes_defined(self, default_mock_concretization, spec_str, expected_url):
 | 
			
		||||
        s = default_mock_concretization(spec_str)
 | 
			
		||||
        assert s.package.urls[0] == expected_url
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize(
 | 
			
		||||
@@ -344,33 +350,33 @@ def test_attributes_defined(self, spec_str, expected_url):
 | 
			
		||||
            ("mirror-xorg-broken", r"{0} must define a `xorg_mirror_path` attribute"),
 | 
			
		||||
        ],
 | 
			
		||||
    )
 | 
			
		||||
    def test_attributes_missing(self, spec_str, error_fmt):
 | 
			
		||||
        s = Spec(spec_str).concretized()
 | 
			
		||||
    def test_attributes_missing(self, default_mock_concretization, spec_str, error_fmt):
 | 
			
		||||
        s = default_mock_concretization(spec_str)
 | 
			
		||||
        error_msg = error_fmt.format(type(s.package).__name__)
 | 
			
		||||
        with pytest.raises(AttributeError, match=error_msg):
 | 
			
		||||
            s.package.urls
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_cmake_define_from_variant_conditional(config, mock_packages):
 | 
			
		||||
def test_cmake_define_from_variant_conditional(default_mock_concretization):
 | 
			
		||||
    """Test that define_from_variant returns empty string when a condition on a variant
 | 
			
		||||
    is not met. When this is the case, the variant is not set in the spec."""
 | 
			
		||||
    s = Spec("cmake-conditional-variants-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("cmake-conditional-variants-test")
 | 
			
		||||
    assert "example" not in s.variants
 | 
			
		||||
    assert s.package.define_from_variant("EXAMPLE", "example") == ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_autotools_args_from_conditional_variant(config, mock_packages):
 | 
			
		||||
def test_autotools_args_from_conditional_variant(default_mock_concretization):
 | 
			
		||||
    """Test that _activate_or_not returns an empty string when a condition on a variant
 | 
			
		||||
    is not met. When this is the case, the variant is not set in the spec."""
 | 
			
		||||
    s = Spec("autotools-conditional-variants-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("autotools-conditional-variants-test")
 | 
			
		||||
    assert "example" not in s.variants
 | 
			
		||||
    assert len(s.package.builder._activate_or_not("example", "enable", "disable")) == 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_autoreconf_search_path_args_multiple(config, mock_packages, tmpdir):
 | 
			
		||||
def test_autoreconf_search_path_args_multiple(default_mock_concretization, tmpdir):
 | 
			
		||||
    """autoreconf should receive the right -I flags with search paths for m4 files
 | 
			
		||||
    for build deps."""
 | 
			
		||||
    spec = Spec("dttop").concretized()
 | 
			
		||||
    spec = default_mock_concretization("dttop")
 | 
			
		||||
    aclocal_fst = str(tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal"))
 | 
			
		||||
    aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
 | 
			
		||||
    build_dep_one, build_dep_two = spec.dependencies(deptype="build")
 | 
			
		||||
@@ -384,11 +390,11 @@ def test_autoreconf_search_path_args_multiple(config, mock_packages, tmpdir):
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_autoreconf_search_path_args_skip_automake(config, mock_packages, tmpdir):
 | 
			
		||||
def test_autoreconf_search_path_args_skip_automake(default_mock_concretization, tmpdir):
 | 
			
		||||
    """automake's aclocal dir should not be added as -I flag as it is a default
 | 
			
		||||
    3rd party dir search path, and if it's a system version it usually includes
 | 
			
		||||
    m4 files shadowing spack deps."""
 | 
			
		||||
    spec = Spec("dttop").concretized()
 | 
			
		||||
    spec = default_mock_concretization("dttop")
 | 
			
		||||
    tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal")
 | 
			
		||||
    aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
 | 
			
		||||
    build_dep_one, build_dep_two = spec.dependencies(deptype="build")
 | 
			
		||||
@@ -398,9 +404,9 @@ def test_autoreconf_search_path_args_skip_automake(config, mock_packages, tmpdir
 | 
			
		||||
    assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == ["-I", aclocal_snd]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_autoreconf_search_path_args_external_order(config, mock_packages, tmpdir):
 | 
			
		||||
def test_autoreconf_search_path_args_external_order(default_mock_concretization, tmpdir):
 | 
			
		||||
    """When a build dep is external, its -I flag should occur last"""
 | 
			
		||||
    spec = Spec("dttop").concretized()
 | 
			
		||||
    spec = default_mock_concretization("dttop")
 | 
			
		||||
    aclocal_fst = str(tmpdir.mkdir("fst").mkdir("share").mkdir("aclocal"))
 | 
			
		||||
    aclocal_snd = str(tmpdir.mkdir("snd").mkdir("share").mkdir("aclocal"))
 | 
			
		||||
    build_dep_one, build_dep_two = spec.dependencies(deptype="build")
 | 
			
		||||
@@ -414,18 +420,18 @@ def test_autoreconf_search_path_args_external_order(config, mock_packages, tmpdi
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_autoreconf_search_path_skip_nonexisting(config, mock_packages, tmpdir):
 | 
			
		||||
def test_autoreconf_search_path_skip_nonexisting(default_mock_concretization, tmpdir):
 | 
			
		||||
    """Skip -I flags for non-existing directories"""
 | 
			
		||||
    spec = Spec("dttop").concretized()
 | 
			
		||||
    spec = default_mock_concretization("dttop")
 | 
			
		||||
    build_dep_one, build_dep_two = spec.dependencies(deptype="build")
 | 
			
		||||
    build_dep_one.prefix = str(tmpdir.join("fst"))
 | 
			
		||||
    build_dep_two.prefix = str(tmpdir.join("snd"))
 | 
			
		||||
    assert spack.build_systems.autotools._autoreconf_search_path_args(spec) == []
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_autoreconf_search_path_dont_repeat(config, mock_packages, tmpdir):
 | 
			
		||||
def test_autoreconf_search_path_dont_repeat(default_mock_concretization, tmpdir):
 | 
			
		||||
    """Do not add the same -I flag twice to keep things readable for humans"""
 | 
			
		||||
    spec = Spec("dttop").concretized()
 | 
			
		||||
    spec = default_mock_concretization("dttop")
 | 
			
		||||
    aclocal = str(tmpdir.mkdir("prefix").mkdir("share").mkdir("aclocal"))
 | 
			
		||||
    build_dep_one, build_dep_two = spec.dependencies(deptype="build")
 | 
			
		||||
    build_dep_one.external_path = str(tmpdir.join("prefix"))
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,6 @@
 | 
			
		||||
import spack.environment as ev
 | 
			
		||||
import spack.error
 | 
			
		||||
import spack.paths as spack_paths
 | 
			
		||||
import spack.spec as spec
 | 
			
		||||
import spack.util.gpg
 | 
			
		||||
import spack.util.spack_yaml as syaml
 | 
			
		||||
 | 
			
		||||
@@ -145,13 +144,12 @@ def test_download_and_extract_artifacts(tmpdir, monkeypatch, working_env):
 | 
			
		||||
        ci.download_and_extract_artifacts(url, working_dir)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_ci_copy_stage_logs_to_artifacts_fail(tmpdir, config, mock_packages, monkeypatch, capfd):
 | 
			
		||||
def test_ci_copy_stage_logs_to_artifacts_fail(tmpdir, default_mock_concretization, capfd):
 | 
			
		||||
    """The copy will fail because the spec is not concrete so does not have
 | 
			
		||||
    a package."""
 | 
			
		||||
    log_dir = tmpdir.join("log_dir")
 | 
			
		||||
    s = spec.Spec("printing-package").concretized()
 | 
			
		||||
 | 
			
		||||
    ci.copy_stage_logs_to_artifacts(s, log_dir)
 | 
			
		||||
    concrete_spec = default_mock_concretization("printing-package")
 | 
			
		||||
    ci.copy_stage_logs_to_artifacts(concrete_spec, log_dir)
 | 
			
		||||
    _, err = capfd.readouterr()
 | 
			
		||||
    assert "Unable to copy files" in err
 | 
			
		||||
    assert "No such file or directory" in err
 | 
			
		||||
@@ -456,17 +454,16 @@ def test_get_spec_filter_list(mutable_mock_env_path, config, mutable_mock_repo):
 | 
			
		||||
    assert affected_pkg_names == expected_affected_pkg_names
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.maybeslow
 | 
			
		||||
@pytest.mark.regression("29947")
 | 
			
		||||
def test_affected_specs_on_first_concretization(mutable_mock_env_path, config):
 | 
			
		||||
def test_affected_specs_on_first_concretization(mutable_mock_env_path, mock_packages, config):
 | 
			
		||||
    e = ev.create("first_concretization")
 | 
			
		||||
    e.add("hdf5~mpi~szip")
 | 
			
		||||
    e.add("hdf5~mpi+szip")
 | 
			
		||||
    e.add("mpileaks~shared")
 | 
			
		||||
    e.add("mpileaks+shared")
 | 
			
		||||
    e.concretize()
 | 
			
		||||
 | 
			
		||||
    affected_specs = spack.ci.get_spec_filter_list(e, ["zlib"])
 | 
			
		||||
    hdf5_specs = [s for s in affected_specs if s.name == "hdf5"]
 | 
			
		||||
    assert len(hdf5_specs) == 2
 | 
			
		||||
    affected_specs = spack.ci.get_spec_filter_list(e, ["callpath"])
 | 
			
		||||
    mpileaks_specs = [s for s in affected_specs if s.name == "mpileaks"]
 | 
			
		||||
    assert len(mpileaks_specs) == 2, e.all_specs()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.skipif(
 | 
			
		||||
@@ -515,14 +512,14 @@ def test_ci_create_buildcache(tmpdir, working_env, config, mock_packages, monkey
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_ci_run_standalone_tests_missing_requirements(
 | 
			
		||||
    tmpdir, working_env, config, mock_packages, capfd
 | 
			
		||||
    tmpdir, working_env, default_mock_concretization, capfd
 | 
			
		||||
):
 | 
			
		||||
    """This test case checks for failing prerequisite checks."""
 | 
			
		||||
    ci.run_standalone_tests()
 | 
			
		||||
    err = capfd.readouterr()[1]
 | 
			
		||||
    assert "Job spec is required" in err
 | 
			
		||||
 | 
			
		||||
    args = {"job_spec": spec.Spec("printing-package").concretized()}
 | 
			
		||||
    args = {"job_spec": default_mock_concretization("printing-package")}
 | 
			
		||||
    ci.run_standalone_tests(**args)
 | 
			
		||||
    err = capfd.readouterr()[1]
 | 
			
		||||
    assert "Reproduction directory is required" in err
 | 
			
		||||
@@ -532,12 +529,12 @@ def test_ci_run_standalone_tests_missing_requirements(
 | 
			
		||||
    sys.platform == "win32", reason="Reliance on bash script not supported on Windows"
 | 
			
		||||
)
 | 
			
		||||
def test_ci_run_standalone_tests_not_installed_junit(
 | 
			
		||||
    tmpdir, working_env, config, mock_packages, mock_test_stage, capfd
 | 
			
		||||
    tmpdir, working_env, default_mock_concretization, mock_test_stage, capfd
 | 
			
		||||
):
 | 
			
		||||
    log_file = tmpdir.join("junit.xml").strpath
 | 
			
		||||
    args = {
 | 
			
		||||
        "log_file": log_file,
 | 
			
		||||
        "job_spec": spec.Spec("printing-package").concretized(),
 | 
			
		||||
        "job_spec": default_mock_concretization("printing-package"),
 | 
			
		||||
        "repro_dir": tmpdir.join("repro_dir").strpath,
 | 
			
		||||
        "fail_fast": True,
 | 
			
		||||
    }
 | 
			
		||||
@@ -553,13 +550,13 @@ def test_ci_run_standalone_tests_not_installed_junit(
 | 
			
		||||
    sys.platform == "win32", reason="Reliance on bash script not supported on Windows"
 | 
			
		||||
)
 | 
			
		||||
def test_ci_run_standalone_tests_not_installed_cdash(
 | 
			
		||||
    tmpdir, working_env, config, mock_packages, mock_test_stage, capfd
 | 
			
		||||
    tmpdir, working_env, default_mock_concretization, mock_test_stage, capfd
 | 
			
		||||
):
 | 
			
		||||
    """Test run_standalone_tests with cdash and related options."""
 | 
			
		||||
    log_file = tmpdir.join("junit.xml").strpath
 | 
			
		||||
    args = {
 | 
			
		||||
        "log_file": log_file,
 | 
			
		||||
        "job_spec": spec.Spec("printing-package").concretized(),
 | 
			
		||||
        "job_spec": default_mock_concretization("printing-package"),
 | 
			
		||||
        "repro_dir": tmpdir.join("repro_dir").strpath,
 | 
			
		||||
    }
 | 
			
		||||
    os.makedirs(args["repro_dir"])
 | 
			
		||||
 
 | 
			
		||||
@@ -1852,3 +1852,27 @@ def _factory(rpaths, message="Hello world!"):
 | 
			
		||||
        return executable
 | 
			
		||||
 | 
			
		||||
    return _factory
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(scope="session")
 | 
			
		||||
def concretized_specs_cache():
 | 
			
		||||
    """Cache for mock concrete specs"""
 | 
			
		||||
    return {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.fixture
 | 
			
		||||
def default_mock_concretization(config, mock_packages, concretized_specs_cache):
 | 
			
		||||
    """Return the default mock concretization of a spec literal, obtained using the mock
 | 
			
		||||
    repository and the mock configuration.
 | 
			
		||||
 | 
			
		||||
    This fixture is unsafe to call in a test when either the default configuration or mock
 | 
			
		||||
    repository are not used or have been modified.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def _func(spec_str, tests=False):
 | 
			
		||||
        key = spec_str, tests
 | 
			
		||||
        if key not in concretized_specs_cache:
 | 
			
		||||
            concretized_specs_cache[key] = spack.spec.Spec(spec_str).concretized(tests=tests)
 | 
			
		||||
        return concretized_specs_cache[key].copy()
 | 
			
		||||
 | 
			
		||||
    return _func
 | 
			
		||||
 
 | 
			
		||||
@@ -835,7 +835,7 @@ def _is(db, spec):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.db
 | 
			
		||||
def test_clear_failure_forced(mutable_database, monkeypatch, capfd):
 | 
			
		||||
def test_clear_failure_forced(default_mock_concretization, mutable_database, monkeypatch, capfd):
 | 
			
		||||
    """Add test coverage for clear_failure operation when force."""
 | 
			
		||||
 | 
			
		||||
    def _is(db, spec):
 | 
			
		||||
@@ -846,7 +846,7 @@ def _is(db, spec):
 | 
			
		||||
    # Ensure raise OSError when try to remove the non-existent marking
 | 
			
		||||
    monkeypatch.setattr(spack.database.Database, "prefix_failure_marked", _is)
 | 
			
		||||
 | 
			
		||||
    s = spack.spec.Spec("a").concretized()
 | 
			
		||||
    s = default_mock_concretization("a")
 | 
			
		||||
    spack.store.db.clear_failure(s, force=True)
 | 
			
		||||
    out = capfd.readouterr()[1]
 | 
			
		||||
    assert "Removing failure marking despite lock" in out
 | 
			
		||||
@@ -854,7 +854,7 @@ def _is(db, spec):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.db
 | 
			
		||||
def test_mark_failed(mutable_database, monkeypatch, tmpdir, capsys):
 | 
			
		||||
def test_mark_failed(default_mock_concretization, mutable_database, monkeypatch, tmpdir, capsys):
 | 
			
		||||
    """Add coverage to mark_failed."""
 | 
			
		||||
 | 
			
		||||
    def _raise_exc(lock):
 | 
			
		||||
@@ -864,7 +864,7 @@ def _raise_exc(lock):
 | 
			
		||||
    monkeypatch.setattr(lk.Lock, "acquire_write", _raise_exc)
 | 
			
		||||
 | 
			
		||||
    with tmpdir.as_cwd():
 | 
			
		||||
        s = spack.spec.Spec("a").concretized()
 | 
			
		||||
        s = default_mock_concretization("a")
 | 
			
		||||
        spack.store.db.mark_failed(s)
 | 
			
		||||
 | 
			
		||||
        out = str(capsys.readouterr()[1])
 | 
			
		||||
@@ -876,13 +876,13 @@ def _raise_exc(lock):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.db
 | 
			
		||||
def test_prefix_failed(mutable_database, monkeypatch):
 | 
			
		||||
def test_prefix_failed(default_mock_concretization, mutable_database, monkeypatch):
 | 
			
		||||
    """Add coverage to prefix_failed operation."""
 | 
			
		||||
 | 
			
		||||
    def _is(db, spec):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    s = spack.spec.Spec("a").concretized()
 | 
			
		||||
    s = default_mock_concretization("a")
 | 
			
		||||
 | 
			
		||||
    # Confirm the spec is not already marked as failed
 | 
			
		||||
    assert not spack.store.db.prefix_failed(s)
 | 
			
		||||
@@ -900,13 +900,13 @@ def _is(db, spec):
 | 
			
		||||
    assert spack.store.db.prefix_failed(s)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_prefix_read_lock_error(mutable_database, monkeypatch):
 | 
			
		||||
def test_prefix_read_lock_error(default_mock_concretization, mutable_database, monkeypatch):
 | 
			
		||||
    """Cover the prefix read lock exception."""
 | 
			
		||||
 | 
			
		||||
    def _raise(db, spec):
 | 
			
		||||
        raise lk.LockError("Mock lock error")
 | 
			
		||||
 | 
			
		||||
    s = spack.spec.Spec("a").concretized()
 | 
			
		||||
    s = default_mock_concretization("a")
 | 
			
		||||
 | 
			
		||||
    # Ensure subsequent lock operations fail
 | 
			
		||||
    monkeypatch.setattr(lk.Lock, "acquire_read", _raise)
 | 
			
		||||
@@ -916,13 +916,13 @@ def _raise(db, spec):
 | 
			
		||||
            assert False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_prefix_write_lock_error(mutable_database, monkeypatch):
 | 
			
		||||
def test_prefix_write_lock_error(default_mock_concretization, mutable_database, monkeypatch):
 | 
			
		||||
    """Cover the prefix write lock exception."""
 | 
			
		||||
 | 
			
		||||
    def _raise(db, spec):
 | 
			
		||||
        raise lk.LockError("Mock lock error")
 | 
			
		||||
 | 
			
		||||
    s = spack.spec.Spec("a").concretized()
 | 
			
		||||
    s = default_mock_concretization("a")
 | 
			
		||||
 | 
			
		||||
    # Ensure subsequent lock operations fail
 | 
			
		||||
    monkeypatch.setattr(lk.Lock, "acquire_write", _raise)
 | 
			
		||||
 
 | 
			
		||||
@@ -24,11 +24,10 @@
 | 
			
		||||
max_packages = 10
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_yaml_directory_layout_parameters(tmpdir, config):
 | 
			
		||||
def test_yaml_directory_layout_parameters(tmpdir, default_mock_concretization):
 | 
			
		||||
    """This tests the various parameters that can be used to configure
 | 
			
		||||
    the install location"""
 | 
			
		||||
    spec = Spec("python")
 | 
			
		||||
    spec.concretize()
 | 
			
		||||
    spec = default_mock_concretization("python")
 | 
			
		||||
 | 
			
		||||
    # Ensure default layout matches expected spec format
 | 
			
		||||
    layout_default = DirectoryLayout(str(tmpdir))
 | 
			
		||||
@@ -215,11 +214,9 @@ def test_find(temporary_store, config, mock_packages):
 | 
			
		||||
        assert found_specs[name].eq_dag(spec)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_yaml_directory_layout_build_path(tmpdir, config):
 | 
			
		||||
def test_yaml_directory_layout_build_path(tmpdir, default_mock_concretization):
 | 
			
		||||
    """This tests build path method."""
 | 
			
		||||
    spec = Spec("python")
 | 
			
		||||
    spec.concretize()
 | 
			
		||||
 | 
			
		||||
    spec = default_mock_concretization("python")
 | 
			
		||||
    layout = DirectoryLayout(str(tmpdir))
 | 
			
		||||
    rel_path = os.path.join(layout.metadata_dir, layout.packages_dir)
 | 
			
		||||
    assert layout.build_packages_path(spec) == os.path.join(spec.prefix, rel_path)
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,13 @@ def test_bad_git(tmpdir, mock_bad_git):
 | 
			
		||||
@pytest.mark.parametrize("type_of_test", ["default", "branch", "tag", "commit"])
 | 
			
		||||
@pytest.mark.parametrize("secure", [True, False])
 | 
			
		||||
def test_fetch(
 | 
			
		||||
    type_of_test, secure, mock_git_repository, config, mutable_mock_repo, git_version, monkeypatch
 | 
			
		||||
    type_of_test,
 | 
			
		||||
    secure,
 | 
			
		||||
    mock_git_repository,
 | 
			
		||||
    default_mock_concretization,
 | 
			
		||||
    mutable_mock_repo,
 | 
			
		||||
    git_version,
 | 
			
		||||
    monkeypatch,
 | 
			
		||||
):
 | 
			
		||||
    """Tries to:
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +110,7 @@ def test_fetch(
 | 
			
		||||
    monkeypatch.delattr(pkg_class, "git")
 | 
			
		||||
 | 
			
		||||
    # Construct the package under test
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    monkeypatch.setitem(s.package.versions, ver("git"), t.args)
 | 
			
		||||
 | 
			
		||||
    # Enter the stage directory and check some properties
 | 
			
		||||
@@ -136,7 +142,7 @@ def test_fetch(
 | 
			
		||||
 | 
			
		||||
@pytest.mark.disable_clean_stage_check
 | 
			
		||||
def test_fetch_pkg_attr_submodule_init(
 | 
			
		||||
    mock_git_repository, config, mutable_mock_repo, monkeypatch, mock_stage
 | 
			
		||||
    mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch, mock_stage
 | 
			
		||||
):
 | 
			
		||||
    """In this case the version() args do not contain a 'git' URL, so
 | 
			
		||||
    the fetcher must be assembled using the Package-level 'git' attribute.
 | 
			
		||||
@@ -151,7 +157,7 @@ def test_fetch_pkg_attr_submodule_init(
 | 
			
		||||
    monkeypatch.setattr(pkg_class, "git", mock_git_repository.url)
 | 
			
		||||
 | 
			
		||||
    # Construct the package under test
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    monkeypatch.setitem(s.package.versions, ver("git"), t.args)
 | 
			
		||||
 | 
			
		||||
    s.package.do_stage()
 | 
			
		||||
@@ -193,13 +199,15 @@ def test_adhoc_version_submodules(
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize("type_of_test", ["branch", "commit"])
 | 
			
		||||
def test_debug_fetch(mock_packages, type_of_test, mock_git_repository, config, monkeypatch):
 | 
			
		||||
def test_debug_fetch(
 | 
			
		||||
    mock_packages, type_of_test, mock_git_repository, default_mock_concretization, monkeypatch
 | 
			
		||||
):
 | 
			
		||||
    """Fetch the repo with debug enabled."""
 | 
			
		||||
    # Retrieve the right test parameters
 | 
			
		||||
    t = mock_git_repository.checks[type_of_test]
 | 
			
		||||
 | 
			
		||||
    # Construct the package under test
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    monkeypatch.setitem(s.package.versions, ver("git"), t.args)
 | 
			
		||||
 | 
			
		||||
    # Fetch then ensure source path exists
 | 
			
		||||
@@ -231,7 +239,12 @@ def test_needs_stage():
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize("get_full_repo", [True, False])
 | 
			
		||||
def test_get_full_repo(
 | 
			
		||||
    get_full_repo, git_version, mock_git_repository, config, mutable_mock_repo, monkeypatch
 | 
			
		||||
    get_full_repo,
 | 
			
		||||
    git_version,
 | 
			
		||||
    mock_git_repository,
 | 
			
		||||
    default_mock_concretization,
 | 
			
		||||
    mutable_mock_repo,
 | 
			
		||||
    monkeypatch,
 | 
			
		||||
):
 | 
			
		||||
    """Ensure that we can clone a full repository."""
 | 
			
		||||
 | 
			
		||||
@@ -243,7 +256,7 @@ def test_get_full_repo(
 | 
			
		||||
 | 
			
		||||
    t = mock_git_repository.checks[type_of_test]
 | 
			
		||||
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    args = copy.copy(t.args)
 | 
			
		||||
    args["get_full_repo"] = get_full_repo
 | 
			
		||||
    monkeypatch.setitem(s.package.versions, ver("git"), args)
 | 
			
		||||
@@ -273,7 +286,9 @@ def test_get_full_repo(
 | 
			
		||||
 | 
			
		||||
@pytest.mark.disable_clean_stage_check
 | 
			
		||||
@pytest.mark.parametrize("submodules", [True, False])
 | 
			
		||||
def test_gitsubmodule(submodules, mock_git_repository, config, mutable_mock_repo, monkeypatch):
 | 
			
		||||
def test_gitsubmodule(
 | 
			
		||||
    submodules, mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch
 | 
			
		||||
):
 | 
			
		||||
    """
 | 
			
		||||
    Test GitFetchStrategy behavior with submodules. This package
 | 
			
		||||
    has a `submodules` property which is always True: when a specific
 | 
			
		||||
@@ -286,7 +301,7 @@ def test_gitsubmodule(submodules, mock_git_repository, config, mutable_mock_repo
 | 
			
		||||
    t = mock_git_repository.checks[type_of_test]
 | 
			
		||||
 | 
			
		||||
    # Construct the package under test
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    args = copy.copy(t.args)
 | 
			
		||||
    args["submodules"] = submodules
 | 
			
		||||
    monkeypatch.setitem(s.package.versions, ver("git"), args)
 | 
			
		||||
@@ -304,7 +319,9 @@ def test_gitsubmodule(submodules, mock_git_repository, config, mutable_mock_repo
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.disable_clean_stage_check
 | 
			
		||||
def test_gitsubmodules_callable(mock_git_repository, config, mutable_mock_repo, monkeypatch):
 | 
			
		||||
def test_gitsubmodules_callable(
 | 
			
		||||
    mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch
 | 
			
		||||
):
 | 
			
		||||
    """
 | 
			
		||||
    Test GitFetchStrategy behavior with submodules selected after concretization
 | 
			
		||||
    """
 | 
			
		||||
@@ -317,7 +334,7 @@ def submodules_callback(package):
 | 
			
		||||
    t = mock_git_repository.checks[type_of_test]
 | 
			
		||||
 | 
			
		||||
    # Construct the package under test
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    args = copy.copy(t.args)
 | 
			
		||||
    args["submodules"] = submodules_callback
 | 
			
		||||
    monkeypatch.setitem(s.package.versions, ver("git"), args)
 | 
			
		||||
@@ -330,7 +347,9 @@ def submodules_callback(package):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.disable_clean_stage_check
 | 
			
		||||
def test_gitsubmodules_delete(mock_git_repository, config, mutable_mock_repo, monkeypatch):
 | 
			
		||||
def test_gitsubmodules_delete(
 | 
			
		||||
    mock_git_repository, default_mock_concretization, mutable_mock_repo, monkeypatch
 | 
			
		||||
):
 | 
			
		||||
    """
 | 
			
		||||
    Test GitFetchStrategy behavior with submodules_delete
 | 
			
		||||
    """
 | 
			
		||||
@@ -338,7 +357,7 @@ def test_gitsubmodules_delete(mock_git_repository, config, mutable_mock_repo, mo
 | 
			
		||||
    t = mock_git_repository.checks[type_of_test]
 | 
			
		||||
 | 
			
		||||
    # Construct the package under test
 | 
			
		||||
    s = Spec("git-test").concretized()
 | 
			
		||||
    s = default_mock_concretization("git-test")
 | 
			
		||||
    args = copy.copy(t.args)
 | 
			
		||||
    args["submodules"] = True
 | 
			
		||||
    args["submodules_delete"] = ["third_party/submodule0", "third_party/submodule1"]
 | 
			
		||||
 
 | 
			
		||||
@@ -570,7 +570,9 @@ def fake_fn(self):
 | 
			
		||||
    "manual,instr", [(False, False), (False, True), (True, False), (True, True)]
 | 
			
		||||
)
 | 
			
		||||
@pytest.mark.disable_clean_stage_check
 | 
			
		||||
def test_manual_download(install_mockery, mock_download, monkeypatch, manual, instr):
 | 
			
		||||
def test_manual_download(
 | 
			
		||||
    install_mockery, mock_download, default_mock_concretization, monkeypatch, manual, instr
 | 
			
		||||
):
 | 
			
		||||
    """
 | 
			
		||||
    Ensure expected fetcher fail message based on manual download and instr.
 | 
			
		||||
    """
 | 
			
		||||
@@ -579,7 +581,7 @@ def test_manual_download(install_mockery, mock_download, monkeypatch, manual, in
 | 
			
		||||
    def _instr(pkg):
 | 
			
		||||
        return "Download instructions for {0}".format(pkg.spec.name)
 | 
			
		||||
 | 
			
		||||
    spec = Spec("a").concretized()
 | 
			
		||||
    spec = default_mock_concretization("a")
 | 
			
		||||
    pkg = spec.package
 | 
			
		||||
 | 
			
		||||
    pkg.manual_download = manual
 | 
			
		||||
@@ -605,16 +607,20 @@ def fetch(self):
 | 
			
		||||
    monkeypatch.setattr(spack.package_base.PackageBase, "fetcher", fetcher)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_fetch_without_code_is_noop(install_mockery, fetching_not_allowed):
 | 
			
		||||
def test_fetch_without_code_is_noop(
 | 
			
		||||
    default_mock_concretization, install_mockery, fetching_not_allowed
 | 
			
		||||
):
 | 
			
		||||
    """do_fetch for packages without code should be a no-op"""
 | 
			
		||||
    pkg = Spec("a").concretized().package
 | 
			
		||||
    pkg = default_mock_concretization("a").package
 | 
			
		||||
    pkg.has_code = False
 | 
			
		||||
    pkg.do_fetch()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_fetch_external_package_is_noop(install_mockery, fetching_not_allowed):
 | 
			
		||||
def test_fetch_external_package_is_noop(
 | 
			
		||||
    default_mock_concretization, install_mockery, fetching_not_allowed
 | 
			
		||||
):
 | 
			
		||||
    """do_fetch for packages without code should be a no-op"""
 | 
			
		||||
    spec = Spec("a").concretized()
 | 
			
		||||
    spec = default_mock_concretization("a")
 | 
			
		||||
    spec.external_path = "/some/where"
 | 
			
		||||
    assert spec.external
 | 
			
		||||
    spec.package.do_fetch()
 | 
			
		||||
 
 | 
			
		||||
@@ -719,9 +719,8 @@ def test_exceptional_paths_for_constructor(self):
 | 
			
		||||
        with pytest.raises(ValueError):
 | 
			
		||||
            Spec("libelf foo")
 | 
			
		||||
 | 
			
		||||
    def test_spec_formatting(self):
 | 
			
		||||
        spec = Spec("multivalue-variant cflags=-O2")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
    def test_spec_formatting(self, default_mock_concretization):
 | 
			
		||||
        spec = default_mock_concretization("multivalue-variant cflags=-O2")
 | 
			
		||||
 | 
			
		||||
        # Since the default is the full spec see if the string rep of
 | 
			
		||||
        # spec is the same as the output of spec.format()
 | 
			
		||||
@@ -797,9 +796,8 @@ def test_spec_formatting(self):
 | 
			
		||||
            actual = spec.format(named_str)
 | 
			
		||||
            assert expected == actual
 | 
			
		||||
 | 
			
		||||
    def test_spec_formatting_escapes(self):
 | 
			
		||||
        spec = Spec("multivalue-variant cflags=-O2")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
    def test_spec_formatting_escapes(self, default_mock_concretization):
 | 
			
		||||
        spec = default_mock_concretization("multivalue-variant cflags=-O2")
 | 
			
		||||
 | 
			
		||||
        sigil_mismatches = [
 | 
			
		||||
            "{@name}",
 | 
			
		||||
@@ -881,7 +879,7 @@ def test_spec_flags_maintain_order(self):
 | 
			
		||||
        # different orderings for repeated concretizations of the same
 | 
			
		||||
        # spec and config
 | 
			
		||||
        spec_str = "libelf %gcc@11.1.0 os=redhat6"
 | 
			
		||||
        for _ in range(25):
 | 
			
		||||
        for _ in range(3):
 | 
			
		||||
            s = Spec(spec_str).concretized()
 | 
			
		||||
            assert all(
 | 
			
		||||
                s.compiler_flags[x] == ["-O0", "-g"] for x in ("cflags", "cxxflags", "fflags")
 | 
			
		||||
@@ -954,13 +952,11 @@ def test_forwarding_of_architecture_attributes(self):
 | 
			
		||||
        assert spec.target < "broadwell"
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice(self, transitive):
 | 
			
		||||
    def test_splice(self, transitive, default_mock_concretization):
 | 
			
		||||
        # Tests the new splice function in Spec using a somewhat simple case
 | 
			
		||||
        # with a variant with a conditional dependency.
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-h+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-h+foo")
 | 
			
		||||
 | 
			
		||||
        # Sanity checking that these are not the same thing.
 | 
			
		||||
        assert dep.dag_hash() != spec["splice-h"].dag_hash()
 | 
			
		||||
@@ -993,11 +989,9 @@ def test_splice(self, transitive):
 | 
			
		||||
        assert out.spliced
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_with_cached_hashes(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-h+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
    def test_splice_with_cached_hashes(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-h+foo")
 | 
			
		||||
 | 
			
		||||
        # monkeypatch hashes so we can test that they are cached
 | 
			
		||||
        spec._hash = "aaaaaa"
 | 
			
		||||
@@ -1014,9 +1008,9 @@ def test_splice_with_cached_hashes(self, transitive):
 | 
			
		||||
        assert out["splice-z"].dag_hash() == out_z_expected.dag_hash()
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_input_unchanged(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t").concretized()
 | 
			
		||||
        dep = Spec("splice-h+foo").concretized()
 | 
			
		||||
    def test_splice_input_unchanged(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-h+foo")
 | 
			
		||||
        orig_spec_hash = spec.dag_hash()
 | 
			
		||||
        orig_dep_hash = dep.dag_hash()
 | 
			
		||||
        spec.splice(dep, transitive)
 | 
			
		||||
@@ -1026,16 +1020,13 @@ def test_splice_input_unchanged(self, transitive):
 | 
			
		||||
        assert dep.dag_hash() == orig_dep_hash
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_subsequent(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-h+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
    def test_splice_subsequent(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-h+foo")
 | 
			
		||||
        out = spec.splice(dep, transitive)
 | 
			
		||||
 | 
			
		||||
        # Now we attempt a second splice.
 | 
			
		||||
        dep = Spec("splice-z+bar")
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
        dep = default_mock_concretization("splice-z+bar")
 | 
			
		||||
 | 
			
		||||
        # Transitivity shouldn't matter since Splice Z has no dependencies.
 | 
			
		||||
        out2 = out.splice(dep, transitive)
 | 
			
		||||
@@ -1046,11 +1037,9 @@ def test_splice_subsequent(self, transitive):
 | 
			
		||||
        assert out2.spliced
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_dict(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-h+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
    def test_splice_dict(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-h+foo")
 | 
			
		||||
        out = spec.splice(dep, transitive)
 | 
			
		||||
 | 
			
		||||
        # Sanity check all hashes are unique...
 | 
			
		||||
@@ -1065,11 +1054,9 @@ def test_splice_dict(self, transitive):
 | 
			
		||||
        assert len(build_spec_nodes) == 1
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_dict_roundtrip(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-h+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
    def test_splice_dict_roundtrip(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-h+foo")
 | 
			
		||||
        out = spec.splice(dep, transitive)
 | 
			
		||||
 | 
			
		||||
        # Sanity check all hashes are unique...
 | 
			
		||||
@@ -1132,21 +1119,17 @@ def test_satisfies_dependencies_ordered(self):
 | 
			
		||||
        assert s.satisfies("mpileaks ^zmpi ^fake", strict=True)
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_swap_names(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-a+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
    def test_splice_swap_names(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-a+foo")
 | 
			
		||||
        out = spec.splice(dep, transitive)
 | 
			
		||||
        assert dep.name in out
 | 
			
		||||
        assert transitive == ("+foo" in out["splice-z"])
 | 
			
		||||
 | 
			
		||||
    @pytest.mark.parametrize("transitive", [True, False])
 | 
			
		||||
    def test_splice_swap_names_mismatch_virtuals(self, transitive):
 | 
			
		||||
        spec = Spec("splice-t")
 | 
			
		||||
        dep = Spec("splice-vh+foo")
 | 
			
		||||
        spec.concretize()
 | 
			
		||||
        dep.concretize()
 | 
			
		||||
    def test_splice_swap_names_mismatch_virtuals(self, default_mock_concretization, transitive):
 | 
			
		||||
        spec = default_mock_concretization("splice-t")
 | 
			
		||||
        dep = default_mock_concretization("splice-vh+foo")
 | 
			
		||||
        with pytest.raises(spack.spec.SpliceError, match="will not provide the same virtuals."):
 | 
			
		||||
            spec.splice(dep, transitive)
 | 
			
		||||
 | 
			
		||||
@@ -1166,12 +1149,11 @@ def test_spec_override(self):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.regression("3887")
 | 
			
		||||
@pytest.mark.parametrize("spec_str", ["git", "hdf5", "py-flake8"])
 | 
			
		||||
def test_is_extension_after_round_trip_to_dict(config, spec_str):
 | 
			
		||||
@pytest.mark.parametrize("spec_str", ["py-extension2", "extension1", "perl-extension"])
 | 
			
		||||
def test_is_extension_after_round_trip_to_dict(config, mock_packages, spec_str):
 | 
			
		||||
    # x is constructed directly from string, y from a
 | 
			
		||||
    # round-trip to dict representation
 | 
			
		||||
    x = Spec(spec_str)
 | 
			
		||||
    x.concretize()
 | 
			
		||||
    x = Spec(spec_str).concretized()
 | 
			
		||||
    y = Spec.from_dict(x.to_dict())
 | 
			
		||||
 | 
			
		||||
    # Using 'y' since the round-trip make us lose build dependencies
 | 
			
		||||
@@ -1231,7 +1213,7 @@ def test_merge_anonymous_spec_with_named_spec(anonymous, named, expected):
 | 
			
		||||
    assert s == Spec(expected)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_spec_installed(install_mockery, database):
 | 
			
		||||
def test_spec_installed(default_mock_concretization, database):
 | 
			
		||||
    """Test whether Spec.installed works."""
 | 
			
		||||
    # a known installed spec should say that it's installed
 | 
			
		||||
    specs = database.query()
 | 
			
		||||
@@ -1244,14 +1226,14 @@ def test_spec_installed(install_mockery, database):
 | 
			
		||||
    assert not spec.installed
 | 
			
		||||
 | 
			
		||||
    # 'a' is not in the mock DB and is not installed
 | 
			
		||||
    spec = Spec("a").concretized()
 | 
			
		||||
    spec = default_mock_concretization("a")
 | 
			
		||||
    assert not spec.installed
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.regression("30678")
 | 
			
		||||
def test_call_dag_hash_on_old_dag_hash_spec(mock_packages, config):
 | 
			
		||||
def test_call_dag_hash_on_old_dag_hash_spec(mock_packages, default_mock_concretization):
 | 
			
		||||
    # create a concrete spec
 | 
			
		||||
    a = Spec("a").concretized()
 | 
			
		||||
    a = default_mock_concretization("a")
 | 
			
		||||
    dag_hashes = {spec.name: spec.dag_hash() for spec in a.traverse()}
 | 
			
		||||
 | 
			
		||||
    # make it look like an old DAG hash spec with no package hash on the spec.
 | 
			
		||||
@@ -1298,9 +1280,9 @@ def test_unsupported_compiler():
 | 
			
		||||
        Spec("gcc%fake-compiler").validate_or_raise()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_package_hash_affects_dunder_and_dag_hash(mock_packages, config):
 | 
			
		||||
    a1 = Spec("a").concretized()
 | 
			
		||||
    a2 = Spec("a").concretized()
 | 
			
		||||
def test_package_hash_affects_dunder_and_dag_hash(mock_packages, default_mock_concretization):
 | 
			
		||||
    a1 = default_mock_concretization("a")
 | 
			
		||||
    a2 = default_mock_concretization("a")
 | 
			
		||||
 | 
			
		||||
    assert hash(a1) == hash(a2)
 | 
			
		||||
    assert a1.dag_hash() == a2.dag_hash()
 | 
			
		||||
 
 | 
			
		||||
@@ -136,18 +136,22 @@ def test_archive_file_errors(tmpdir, mock_archive, _fetch_method):
 | 
			
		||||
@pytest.mark.parametrize("secure", [True, False])
 | 
			
		||||
@pytest.mark.parametrize("_fetch_method", ["curl", "urllib"])
 | 
			
		||||
@pytest.mark.parametrize("mock_archive", files, indirect=True)
 | 
			
		||||
def test_fetch(mock_archive, secure, _fetch_method, checksum_type, config, mutable_mock_repo):
 | 
			
		||||
def test_fetch(
 | 
			
		||||
    mock_archive,
 | 
			
		||||
    secure,
 | 
			
		||||
    _fetch_method,
 | 
			
		||||
    checksum_type,
 | 
			
		||||
    default_mock_concretization,
 | 
			
		||||
    mutable_mock_repo,
 | 
			
		||||
):
 | 
			
		||||
    """Fetch an archive and make sure we can checksum it."""
 | 
			
		||||
    mock_archive.url
 | 
			
		||||
    mock_archive.path
 | 
			
		||||
 | 
			
		||||
    algo = crypto.hash_fun_for_algo(checksum_type)()
 | 
			
		||||
    with open(mock_archive.archive_file, "rb") as f:
 | 
			
		||||
        algo.update(f.read())
 | 
			
		||||
    checksum = algo.hexdigest()
 | 
			
		||||
 | 
			
		||||
    # Get a spec and tweak the test package with new chcecksum params
 | 
			
		||||
    s = Spec("url-test").concretized()
 | 
			
		||||
    # Get a spec and tweak the test package with new checksum params
 | 
			
		||||
    s = default_mock_concretization("url-test")
 | 
			
		||||
    s.package.url = mock_archive.url
 | 
			
		||||
    s.package.versions[ver("test")] = {checksum_type: checksum, "url": s.package.url}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user