summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn W. Parent <45471568+johnwparent@users.noreply.github.com>2022-12-09 08:27:46 -0500
committerGitHub <noreply@github.com>2022-12-09 13:27:46 +0000
commit0e69710f417dce418ca1e3b54ff448493b102c06 (patch)
tree6858421b0088c8fd158e6425c79c98fc19fc4af3 /lib
parentec62150ed7e8c26eff322ffa66f0e7b4c8409734 (diff)
downloadspack-0e69710f417dce418ca1e3b54ff448493b102c06.tar.gz
spack-0e69710f417dce418ca1e3b54ff448493b102c06.tar.bz2
spack-0e69710f417dce418ca1e3b54ff448493b102c06.tar.xz
spack-0e69710f417dce418ca1e3b54ff448493b102c06.zip
Windows: reenable unit tests (#33385)
Unit tests on Windows are supposed to pass for any PR to pass CI. However, the return code for the unit test command was not being checked, which meant this check was always passing (effectively disabled). This PR * Properly checks the result of the unit tests and fails if the unit tests fail * Fixes (or disables on Windows) a number of tests which have "drifted" out of support on Windows since this check was effectively disabled
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/llnl/util/filesystem.py9
-rw-r--r--lib/spack/spack/bootstrap/core.py3
-rw-r--r--lib/spack/spack/compiler.py14
-rw-r--r--lib/spack/spack/compilers/__init__.py2
-rw-r--r--lib/spack/spack/compilers/msvc.py8
-rw-r--r--lib/spack/spack/spec.py10
-rw-r--r--lib/spack/spack/test/builder.py5
-rw-r--r--lib/spack/spack/test/cmd/external.py2
-rw-r--r--lib/spack/spack/test/cmd/list.py19
-rw-r--r--lib/spack/spack/test/cmd/uninstall.py4
-rw-r--r--lib/spack/spack/test/concretize.py16
-rw-r--r--lib/spack/spack/test/concretize_preferences.py4
-rw-r--r--lib/spack/spack/test/conftest.py11
-rw-r--r--lib/spack/spack/test/database.py4
-rw-r--r--lib/spack/spack/test/installer.py2
-rw-r--r--lib/spack/spack/test/spec_syntax.py5
-rw-r--r--lib/spack/spack/util/path.py2
17 files changed, 88 insertions, 32 deletions
diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py
index 388c6fd173..8e664cc0a9 100644
--- a/lib/spack/llnl/util/filesystem.py
+++ b/lib/spack/llnl/util/filesystem.py
@@ -99,7 +99,9 @@ def getuid():
def rename(src, dst):
# On Windows, os.rename will fail if the destination file already exists
if is_windows:
- if os.path.exists(dst):
+ # Windows path existence checks will sometimes fail on junctions/links/symlinks
+ # so check for that case
+ if os.path.exists(dst) or os.path.islink(dst):
os.remove(dst)
os.rename(src, dst)
@@ -288,7 +290,10 @@ def filter_file(regex, repl, *filenames, **kwargs):
shutil.copy(filename, tmp_filename)
try:
- extra_kwargs = {"errors": "surrogateescape"}
+ # To avoid translating line endings (\n to \r\n and vis versa)
+ # we force os.open to ignore translations and use the line endings
+ # the file comes with
+ extra_kwargs = {"errors": "surrogateescape", "newline": ""}
# Open as a text file and filter until the end of the file is
# reached or we found a marker in the line if it was specified
diff --git a/lib/spack/spack/bootstrap/core.py b/lib/spack/spack/bootstrap/core.py
index 9cf25b29e9..e8cb429fa8 100644
--- a/lib/spack/spack/bootstrap/core.py
+++ b/lib/spack/spack/bootstrap/core.py
@@ -545,8 +545,9 @@ def ensure_core_dependencies():
"""Ensure the presence of all the core dependencies."""
if sys.platform.lower() == "linux":
ensure_patchelf_in_path_or_raise()
+ if not IS_WINDOWS:
+ ensure_gpg_in_path_or_raise()
ensure_clingo_importable_or_raise()
- ensure_gpg_in_path_or_raise()
def all_core_root_specs():
diff --git a/lib/spack/spack/compiler.py b/lib/spack/spack/compiler.py
index 8b3afefa42..52c2db8c79 100644
--- a/lib/spack/spack/compiler.py
+++ b/lib/spack/spack/compiler.py
@@ -9,6 +9,7 @@ import os
import platform
import re
import shutil
+import sys
import tempfile
from typing import List, Optional, Sequence
@@ -27,6 +28,8 @@ from spack.util.path import system_path_filter
__all__ = ["Compiler"]
+is_windows = sys.platform == "win32"
+
@llnl.util.lang.memoized
def _get_compiler_version_output(compiler_path, version_arg, ignore_errors=()):
@@ -592,7 +595,16 @@ class Compiler(object):
# defined for the compiler
compiler_names = getattr(cls, "{0}_names".format(language))
prefixes = [""] + cls.prefixes
- suffixes = [""] + cls.suffixes
+ suffixes = [""]
+ # Windows compilers generally have an extension of some sort
+ # as do most files on Windows, handle that case here
+ if is_windows:
+ ext = r"\.(?:exe|bat)"
+ cls_suf = [suf + ext for suf in cls.suffixes]
+ ext_suf = [ext]
+ suffixes = suffixes + cls.suffixes + cls_suf + ext_suf
+ else:
+ suffixes = suffixes + cls.suffixes
regexp_fmt = r"^({0}){1}({2})$"
return [
re.compile(regexp_fmt.format(prefix, re.escape(name), suffix))
diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py
index d4aa54282b..3df8c4b218 100644
--- a/lib/spack/spack/compilers/__init__.py
+++ b/lib/spack/spack/compilers/__init__.py
@@ -722,6 +722,8 @@ def make_compiler_list(detected_versions):
compiler_cls = spack.compilers.class_for_compiler_name(compiler_name)
spec = spack.spec.CompilerSpec(compiler_cls.name, version)
paths = [paths.get(x, None) for x in ("cc", "cxx", "f77", "fc")]
+ # TODO: johnwparent - revist the following line as per discussion at:
+ # https://github.com/spack/spack/pull/33385/files#r1040036318
target = archspec.cpu.host()
compiler = compiler_cls(spec, operating_system, str(target.family), paths)
return [compiler]
diff --git a/lib/spack/spack/compilers/msvc.py b/lib/spack/spack/compilers/msvc.py
index f26dcc78ec..d7576b78e6 100644
--- a/lib/spack/spack/compilers/msvc.py
+++ b/lib/spack/spack/compilers/msvc.py
@@ -42,16 +42,16 @@ def get_valid_fortran_pth(comp_ver):
class Msvc(Compiler):
# Subclasses use possible names of C compiler
- cc_names: List[str] = ["cl.exe"]
+ cc_names: List[str] = ["cl"]
# Subclasses use possible names of C++ compiler
- cxx_names: List[str] = ["cl.exe"]
+ cxx_names: List[str] = ["cl"]
# Subclasses use possible names of Fortran 77 compiler
- f77_names: List[str] = ["ifx.exe"]
+ f77_names: List[str] = ["ifx"]
# Subclasses use possible names of Fortran 90 compiler
- fc_names: List[str] = ["ifx.exe"]
+ fc_names: List[str] = ["ifx"]
# Named wrapper links within build_env_path
# Due to the challenges of supporting compiler wrappers
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 6524bf3bef..012a75c89c 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -1289,7 +1289,7 @@ class Spec(object):
# have package.py files for.
self._normal = normal
self._concrete = concrete
- self.external_path = external_path
+ self._external_path = external_path
self.external_modules = Spec._format_module_list(external_modules)
# This attribute is used to store custom information for
@@ -1327,6 +1327,14 @@ class Spec(object):
return modules
@property
+ def external_path(self):
+ return pth.path_to_os_path(self._external_path)[0]
+
+ @external_path.setter
+ def external_path(self, ext_path):
+ self._external_path = ext_path
+
+ @property
def external(self):
return bool(self.external_path) or bool(self.external_modules)
diff --git a/lib/spack/spack/test/builder.py b/lib/spack/spack/test/builder.py
index efba6aacf1..944514b610 100644
--- a/lib/spack/spack/test/builder.py
+++ b/lib/spack/spack/test/builder.py
@@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
+import sys
import pytest
@@ -123,6 +124,10 @@ def test_old_style_compatibility_with_super(spec_str, method_name, expected):
assert value == expected
+@pytest.mark.skipif(
+ sys.platform == "win32",
+ reason="log_ouput cannot currently be used outside of subprocess on Windows",
+)
@pytest.mark.regression("33928")
@pytest.mark.usefixtures("builder_test_repository", "config", "working_env")
@pytest.mark.disable_clean_stage_check
diff --git a/lib/spack/spack/test/cmd/external.py b/lib/spack/spack/test/cmd/external.py
index 1944a2e940..9b9376ecb1 100644
--- a/lib/spack/spack/test/cmd/external.py
+++ b/lib/spack/spack/test/cmd/external.py
@@ -347,7 +347,7 @@ def test_overriding_prefix(mock_executable, mutable_config, monkeypatch, _platfo
assert "externals" in packages_yaml["gcc"]
externals = packages_yaml["gcc"]["externals"]
assert len(externals) == 1
- assert externals[0]["prefix"] == "/opt/gcc/bin"
+ assert externals[0]["prefix"] == os.path.sep + os.path.join("opt", "gcc", "bin")
def test_new_entries_are_reported_correctly(
diff --git a/lib/spack/spack/test/cmd/list.py b/lib/spack/spack/test/cmd/list.py
index ed5b2574f0..3ebcb4fa39 100644
--- a/lib/spack/spack/test/cmd/list.py
+++ b/lib/spack/spack/test/cmd/list.py
@@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+import sys
from textwrap import dedent
from spack.main import SpackCommand
@@ -18,12 +19,24 @@ def test_list():
def test_list_cli_output_format(mock_tty_stdout):
out = list("mpileaks")
- assert out == dedent(
- """\
+ # Currently logging on Windows detaches stdout
+ # from the terminal so we miss some output during tests
+ # TODO: (johnwparent): Once logging is amended on Windows,
+ # restore this test
+ if not sys.platform == "win32":
+ out_str = dedent(
+ """\
mpileaks
==> 1 packages
"""
- )
+ )
+ else:
+ out_str = dedent(
+ """\
+ mpileaks
+ """
+ )
+ assert out == out_str
def test_list_filter(mock_packages):
diff --git a/lib/spack/spack/test/cmd/uninstall.py b/lib/spack/spack/test/cmd/uninstall.py
index be9fa3aa16..7798e03533 100644
--- a/lib/spack/spack/test/cmd/uninstall.py
+++ b/lib/spack/spack/test/cmd/uninstall.py
@@ -208,9 +208,7 @@ def test_in_memory_consistency_when_uninstalling(mutable_database, monkeypatch):
# Note: I want to use https://docs.pytest.org/en/7.1.x/how-to/skipping.html#skip-all-test-functions-of-a-class-or-module
# the style formatter insists on separating these two lines.
-pytest.mark.skipif(sys.platform == "win32", reason="Envs unsupported on Windows")
-
-
+@pytest.mark.skipif(sys.platform == "win32", reason="Envs unsupported on Windows")
class TestUninstallFromEnv(object):
"""Tests an installation with two environments e1 and e2, which each have
shared package installations:
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 0ddc93b5f6..83597c7f3d 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -3,7 +3,6 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
-import posixpath
import sys
import jinja2
@@ -339,7 +338,7 @@ class TestConcretize(object):
assert spec.satisfies("^openblas cflags='-g'")
@pytest.mark.skipif(
- os.environ.get("SPACK_TEST_SOLVER") == "original" or sys.platform == "win32",
+ os.environ.get("SPACK_TEST_SOLVER") == "original",
reason="Optional compiler propagation isn't deprecated for original concretizer",
)
def test_concretize_compiler_flag_does_not_propagate(self):
@@ -349,7 +348,7 @@ class TestConcretize(object):
assert not spec.satisfies("^openblas cflags='-g'")
@pytest.mark.skipif(
- os.environ.get("SPACK_TEST_SOLVER") == "original" or sys.platform == "win32",
+ os.environ.get("SPACK_TEST_SOLVER") == "original",
reason="Optional compiler propagation isn't deprecated for original concretizer",
)
def test_concretize_propagate_compiler_flag_not_passed_to_dependent(self):
@@ -449,7 +448,7 @@ class TestConcretize(object):
s.concretize()
@pytest.mark.skipif(
- os.environ.get("SPACK_TEST_SOLVER") == "original" or sys.platform == "win32",
+ os.environ.get("SPACK_TEST_SOLVER") == "original",
reason="Optional compiler propagation isn't deprecated for original concretizer",
)
def test_concretize_propagate_disabled_variant(self):
@@ -466,7 +465,6 @@ class TestConcretize(object):
assert spec.satisfies("^openblas+shared")
- @pytest.mark.skipif(sys.platform == "win32", reason="No Compiler for Arch on Win")
def test_no_matching_compiler_specs(self, mock_low_high_config):
# only relevant when not building compilers as needed
with spack.concretize.enable_compiler_existence_check():
@@ -527,7 +525,7 @@ class TestConcretize(object):
def test_external_package(self):
spec = Spec("externaltool%gcc")
spec.concretize()
- assert spec["externaltool"].external_path == posixpath.sep + posixpath.join(
+ assert spec["externaltool"].external_path == os.path.sep + os.path.join(
"path", "to", "external_tool"
)
assert "externalprereq" not in spec
@@ -558,10 +556,10 @@ class TestConcretize(object):
def test_external_and_virtual(self):
spec = Spec("externaltest")
spec.concretize()
- assert spec["externaltool"].external_path == posixpath.sep + posixpath.join(
+ assert spec["externaltool"].external_path == os.path.sep + os.path.join(
"path", "to", "external_tool"
)
- assert spec["stuff"].external_path == posixpath.sep + posixpath.join(
+ assert spec["stuff"].external_path == os.path.sep + os.path.join(
"path", "to", "external_virtual_gcc"
)
assert spec["externaltool"].compiler.satisfies("gcc")
@@ -1815,7 +1813,6 @@ class TestConcretize(object):
c = s.concretized()
assert hash in str(c)
- @pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows (yet)")
@pytest.mark.parametrize("git_ref", ("a" * 40, "0.2.15", "main"))
def test_git_ref_version_is_equivalent_to_specified_version(self, git_ref):
if spack.config.get("config:concretizer") == "original":
@@ -1827,7 +1824,6 @@ class TestConcretize(object):
assert s.satisfies("@develop")
assert s.satisfies("@0.1:")
- @pytest.mark.skipif(sys.platform == "win32", reason="Not supported on Windows (yet)")
@pytest.mark.parametrize("git_ref", ("a" * 40, "0.2.15", "fbranch"))
def test_git_ref_version_errors_if_unknown_version(self, git_ref):
if spack.config.get("config:concretizer") == "original":
diff --git a/lib/spack/spack/test/concretize_preferences.py b/lib/spack/spack/test/concretize_preferences.py
index b0ae008a72..1ebbfacfdd 100644
--- a/lib/spack/spack/test/concretize_preferences.py
+++ b/lib/spack/spack/test/concretize_preferences.py
@@ -270,7 +270,7 @@ mpich:
# ensure that once config is in place, external is used
spec = Spec("mpi")
spec.concretize()
- assert spec["mpich"].external_path == os.sep + os.path.join("dummy", "path")
+ assert spec["mpich"].external_path == os.path.sep + os.path.join("dummy", "path")
def test_external_module(self, monkeypatch):
"""Test that packages can find externals specified by module
@@ -305,7 +305,7 @@ mpi:
# ensure that once config is in place, external is used
spec = Spec("mpi")
spec.concretize()
- assert spec["mpich"].external_path == "/dummy/path"
+ assert spec["mpich"].external_path == os.path.sep + os.path.join("dummy", "path")
def test_buildable_false(self):
conf = syaml.load_config(
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index 0449cd8cf8..2d9e72a89e 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -259,6 +259,17 @@ def _verify_executables_noop(*args):
return None
+def _host():
+ """Mock archspec host so there is no inconsistency on the Windows platform
+ This function cannot be local as it needs to be pickleable"""
+ return archspec.cpu.Microarchitecture("x86_64", [], "generic", [], {}, 0)
+
+
+@pytest.fixture(scope="function")
+def archspec_host_is_spack_test_host(monkeypatch):
+ monkeypatch.setattr(archspec.cpu, "host", _host)
+
+
#
# Disable checks on compiler executable existence
#
diff --git a/lib/spack/spack/test/database.py b/lib/spack/spack/test/database.py
index 99e1b5c470..387daba1b5 100644
--- a/lib/spack/spack/test/database.py
+++ b/lib/spack/spack/test/database.py
@@ -719,13 +719,13 @@ def test_external_entries_in_db(mutable_database):
assert not rec.spec.external_modules
rec = mutable_database.get_record("externaltool")
- assert rec.spec.external_path == os.sep + os.path.join("path", "to", "external_tool")
+ assert rec.spec.external_path == os.path.sep + os.path.join("path", "to", "external_tool")
assert not rec.spec.external_modules
assert rec.explicit is False
rec.spec.package.do_install(fake=True, explicit=True)
rec = mutable_database.get_record("externaltool")
- assert rec.spec.external_path == os.sep + os.path.join("path", "to", "external_tool")
+ assert rec.spec.external_path == os.path.sep + os.path.join("path", "to", "external_tool")
assert not rec.spec.external_modules
assert rec.explicit is True
diff --git a/lib/spack/spack/test/installer.py b/lib/spack/spack/test/installer.py
index 4c85f4ba26..8a446c650e 100644
--- a/lib/spack/spack/test/installer.py
+++ b/lib/spack/spack/test/installer.py
@@ -488,7 +488,7 @@ def test_update_tasks_for_compiler_packages_as_compiler(mock_packages, config, m
def test_bootstrapping_compilers_with_different_names_from_spec(
- install_mockery, mutable_config, mock_fetch
+ install_mockery, mutable_config, mock_fetch, archspec_host_is_spack_test_host
):
with spack.config.override("config:install_missing_compilers", True):
with spack.concretize.disable_compiler_existence_check():
diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py
index 97c1a9a3ce..1a7d52e781 100644
--- a/lib/spack/spack/test/spec_syntax.py
+++ b/lib/spack/spack/test/spec_syntax.py
@@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import itertools
+import sys
import pytest
@@ -11,6 +12,8 @@ import spack.spec
import spack.variant
from spack.parser import SpecParser, SpecTokenizationError, Token, TokenType
+is_windows = sys.platform == "win32"
+
def simple_package_name(name):
"""A simple package name in canonical form"""
@@ -834,6 +837,7 @@ def test_error_conditions(text, exc_cls):
SpecParser(text).next_spec()
+@pytest.mark.skipif(is_windows, reason="Spec parsing does not currently support Windows paths")
def test_parse_specfile_simple(specfile_for, tmpdir):
specfile = tmpdir.join("libdwarf.json")
s = specfile_for("libdwarf", specfile)
@@ -879,6 +883,7 @@ def test_parse_filename_missing_slash_as_spec(specfile_for, tmpdir, filename):
)
+@pytest.mark.skipif(is_windows, reason="Spec parsing does not currently support Windows paths")
def test_parse_specfile_dependency(default_mock_concretization, tmpdir):
"""Ensure we can use a specfile as a dependency"""
s = default_mock_concretization("libdwarf")
diff --git a/lib/spack/spack/util/path.py b/lib/spack/spack/util/path.py
index 2dc646418e..9434fc5af4 100644
--- a/lib/spack/spack/util/path.py
+++ b/lib/spack/spack/util/path.py
@@ -122,7 +122,7 @@ def path_to_os_path(*pths):
"""
ret_pths = []
for pth in pths:
- if type(pth) is str and not is_path_url(pth):
+ if isinstance(pth, str) and not is_path_url(pth):
pth = convert_to_platform_path(pth)
ret_pths.append(pth)
return ret_pths