From 0e69710f417dce418ca1e3b54ff448493b102c06 Mon Sep 17 00:00:00 2001 From: "John W. Parent" <45471568+johnwparent@users.noreply.github.com> Date: Fri, 9 Dec 2022 08:27:46 -0500 Subject: [PATCH] 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 --- .github/workflows/setup_git.ps1 | 4 +- .github/workflows/windows_python.yml | 163 +++++++++--------- lib/spack/llnl/util/filesystem.py | 9 +- lib/spack/spack/bootstrap/core.py | 3 +- lib/spack/spack/compiler.py | 14 +- lib/spack/spack/compilers/__init__.py | 2 + lib/spack/spack/compilers/msvc.py | 8 +- lib/spack/spack/spec.py | 10 +- lib/spack/spack/test/builder.py | 5 + lib/spack/spack/test/cmd/external.py | 2 +- lib/spack/spack/test/cmd/list.py | 19 +- lib/spack/spack/test/cmd/uninstall.py | 4 +- lib/spack/spack/test/concretize.py | 16 +- .../spack/test/concretize_preferences.py | 4 +- lib/spack/spack/test/conftest.py | 11 ++ lib/spack/spack/test/database.py | 4 +- lib/spack/spack/test/installer.py | 2 +- lib/spack/spack/test/spec_syntax.py | 5 + lib/spack/spack/util/path.py | 2 +- share/spack/qa/setup_spack.ps1 | 3 - share/spack/qa/setup_spack_installer.ps1 | 2 + share/spack/qa/validate_last_exit.ps1 | 3 + share/spack/qa/windows_test_setup.ps1 | 16 +- .../intel-oneapi-compilers/package.py | 14 +- 24 files changed, 190 insertions(+), 135 deletions(-) delete mode 100644 share/spack/qa/setup_spack.ps1 create mode 100644 share/spack/qa/setup_spack_installer.ps1 create mode 100644 share/spack/qa/validate_last_exit.ps1 diff --git a/.github/workflows/setup_git.ps1 b/.github/workflows/setup_git.ps1 index 0acb9a9f46..b403ff5ef1 100644 --- a/.github/workflows/setup_git.ps1 +++ b/.github/workflows/setup_git.ps1 @@ -1,6 +1,4 @@ -# (c) 2021 Lawrence Livermore National Laboratory - -Set-Location spack +# (c) 2022 Lawrence Livermore National Laboratory git config --global user.email "spack@example.com" git config --global user.name "Test User" diff --git a/.github/workflows/windows_python.yml b/.github/workflows/windows_python.yml index 05a98c4cba..783ef16252 100644 --- a/.github/workflows/windows_python.yml +++ b/.github/workflows/windows_python.yml @@ -10,7 +10,7 @@ concurrency: defaults: run: shell: - powershell Invoke-Expression -Command ".\share\spack\qa\windows_test_setup.ps1"; {0} + powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0} jobs: unit-tests: runs-on: windows-latest @@ -26,13 +26,11 @@ jobs: python -m pip install --upgrade pip six pywin32 setuptools codecov pytest-cov clingo - name: Create local develop run: | - .\spack\.github\workflows\setup_git.ps1 + ./.github/workflows/setup_git.ps1 - name: Unit Test run: | - echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml - cd spack - dir spack unit-test -x --verbose --cov --cov-config=pyproject.toml --ignore=lib/spack/spack/test/cmd + ./share/spack/qa/validate_last_exit.ps1 coverage combine -a coverage xml - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 @@ -52,12 +50,11 @@ jobs: python -m pip install --upgrade pip six pywin32 setuptools codecov coverage pytest-cov clingo - name: Create local develop run: | - .\spack\.github\workflows\setup_git.ps1 + ./.github/workflows/setup_git.ps1 - name: Command Unit Test run: | - echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml - cd spack spack unit-test -x --verbose --cov --cov-config=pyproject.toml lib/spack/spack/test/cmd + ./share/spack/qa/validate_last_exit.ps1 coverage combine -a coverage xml - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 @@ -78,81 +75,81 @@ jobs: - name: Build Test run: | spack compiler find - echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml spack external find cmake spack external find ninja spack -d install abseil-cpp - make-installer: - runs-on: windows-latest - steps: - - name: Disable Windows Symlinks - run: | - git config --global core.symlinks false - shell: - powershell - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - with: - fetch-depth: 0 - - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 - with: - python-version: 3.9 - - name: Install Python packages - run: | - python -m pip install --upgrade pip six pywin32 setuptools - - name: Add Light and Candle to Path - run: | - $env:WIX >> $GITHUB_PATH - - name: Run Installer - run: | - .\spack\share\spack\qa\setup_spack.ps1 - spack make-installer -s spack -g SILENT pkg - echo "installer_root=$((pwd).Path)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - env: - ProgressPreference: SilentlyContinue - - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb - with: - name: Windows Spack Installer Bundle - path: ${{ env.installer_root }}\pkg\Spack.exe - - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb - with: - name: Windows Spack Installer - path: ${{ env.installer_root}}\pkg\Spack.msi - execute-installer: - needs: make-installer - runs-on: windows-latest - defaults: - run: - shell: pwsh - steps: - - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 - with: - python-version: 3.9 - - name: Install Python packages - run: | - python -m pip install --upgrade pip six pywin32 setuptools - - name: Setup installer directory - run: | - mkdir -p spack_installer - echo "spack_installer=$((pwd).Path)\spack_installer" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - - uses: actions/download-artifact@v3 - with: - name: Windows Spack Installer Bundle - path: ${{ env.spack_installer }} - - name: Execute Bundled Installer - run: | - $proc = Start-Process ${{ env.spack_installer }}\spack.exe "/install /quiet" -Passthru - $handle = $proc.Handle # cache proc.Handle - $proc.WaitForExit(); - $LASTEXITCODE - env: - ProgressPreference: SilentlyContinue - - uses: actions/download-artifact@v3 - with: - name: Windows Spack Installer - path: ${{ env.spack_installer }} - - name: Execute MSI - run: | - $proc = Start-Process ${{ env.spack_installer }}\spack.msi "/quiet" -Passthru - $handle = $proc.Handle # cache proc.Handle - $proc.WaitForExit(); - $LASTEXITCODE + # TODO: johnwparent - reduce the size of the installer operations + # make-installer: + # runs-on: windows-latest + # steps: + # - name: Disable Windows Symlinks + # run: | + # git config --global core.symlinks false + # shell: + # powershell + # - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + # with: + # fetch-depth: 0 + # - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 + # with: + # python-version: 3.9 + # - name: Install Python packages + # run: | + # python -m pip install --upgrade pip six pywin32 setuptools + # - name: Add Light and Candle to Path + # run: | + # $env:WIX >> $GITHUB_PATH + # - name: Run Installer + # run: | + # ./share/spack/qa/setup_spack_installer.ps1 + # spack make-installer -s . -g SILENT pkg + # echo "installer_root=$((pwd).Path)" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + # env: + # ProgressPreference: SilentlyContinue + # - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb + # with: + # name: Windows Spack Installer Bundle + # path: ${{ env.installer_root }}\pkg\Spack.exe + # - uses: actions/upload-artifact@83fd05a356d7e2593de66fc9913b3002723633cb + # with: + # name: Windows Spack Installer + # path: ${{ env.installer_root}}\pkg\Spack.msi + # execute-installer: + # needs: make-installer + # runs-on: windows-latest + # defaults: + # run: + # shell: pwsh + # steps: + # - uses: actions/setup-python@13ae5bb136fac2878aff31522b9efb785519f984 + # with: + # python-version: 3.9 + # - name: Install Python packages + # run: | + # python -m pip install --upgrade pip six pywin32 setuptools + # - name: Setup installer directory + # run: | + # mkdir -p spack_installer + # echo "spack_installer=$((pwd).Path)\spack_installer" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + # - uses: actions/download-artifact@v3 + # with: + # name: Windows Spack Installer Bundle + # path: ${{ env.spack_installer }} + # - name: Execute Bundled Installer + # run: | + # $proc = Start-Process ${{ env.spack_installer }}\spack.exe "/install /quiet" -Passthru + # $handle = $proc.Handle # cache proc.Handle + # $proc.WaitForExit(); + # $LASTEXITCODE + # env: + # ProgressPreference: SilentlyContinue + # - uses: actions/download-artifact@v3 + # with: + # name: Windows Spack Installer + # path: ${{ env.spack_installer }} + # - name: Execute MSI + # run: | + # $proc = Start-Process ${{ env.spack_installer }}\spack.msi "/quiet" -Passthru + # $handle = $proc.Handle # cache proc.Handle + # $proc.WaitForExit(); + # $LASTEXITCODE 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 groupid_to_group(x): 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 platform import re import shutil +import sys import tempfile from typing import List, Optional, Sequence @@ -27,6 +28,8 @@ __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 @@ def search_regexps(cls, language): # 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 _default_make_compilers(cmp_id, paths): 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 @@ def __init__( # 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 @@ -1326,6 +1326,14 @@ def _format_module_list(modules): modules = list(modules) 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 _determine_variants(cls, exes, version_str): 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 _warn(*args, **kwargs): # 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 @@ def test_concretize_compiler_flag_propagate(self): 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 @@ def test_concretize_compiler_flag_does_not_propagate(self): 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 @@ def test_concretize_two_virtuals_with_dual_provider_and_a_conflict(self): 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 @@ def test_concretize_propagated_variant_is_not_passed_to_dependent(self): 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 @@ def test_compiler_inheritance(self, compiler_str): 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 @@ def test_nobuild_package(self): 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 @@ def test_git_hash_assigned_version_is_preferred(self): 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 @@ def test_git_ref_version_is_equivalent_to_specified_version(self, git_ref): 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 @@ def test_external_mpi(self): # 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 @@ def mock_module(cmd, module): # 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 fake_package_list(compiler, architecture, pkgs): 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.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 diff --git a/share/spack/qa/setup_spack.ps1 b/share/spack/qa/setup_spack.ps1 deleted file mode 100644 index 6b462916fa..0000000000 --- a/share/spack/qa/setup_spack.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -spack compiler find -echo F|xcopy .\spack\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml -spack external find cmake \ No newline at end of file diff --git a/share/spack/qa/setup_spack_installer.ps1 b/share/spack/qa/setup_spack_installer.ps1 new file mode 100644 index 0000000000..f2acdcc50a --- /dev/null +++ b/share/spack/qa/setup_spack_installer.ps1 @@ -0,0 +1,2 @@ +spack compiler find +spack external find cmake \ No newline at end of file diff --git a/share/spack/qa/validate_last_exit.ps1 b/share/spack/qa/validate_last_exit.ps1 new file mode 100644 index 0000000000..c8a9f7f5be --- /dev/null +++ b/share/spack/qa/validate_last_exit.ps1 @@ -0,0 +1,3 @@ +if ($LASTEXITCODE -ne 0){ + throw "Unit Tests have failed" +} \ No newline at end of file diff --git a/share/spack/qa/windows_test_setup.ps1 b/share/spack/qa/windows_test_setup.ps1 index a7e3c66ea3..2e25d95960 100644 --- a/share/spack/qa/windows_test_setup.ps1 +++ b/share/spack/qa/windows_test_setup.ps1 @@ -1,11 +1,5 @@ -Set-Location ../ - -$env:python_pf_ver="C:\hostedtoolcache\windows\Python\3.9.5\x64\python.exe" - -cmd /c "`"spack\bin\spack_cmd.bat`" print " | -foreach { - if ($_ -match "=") { - $v = $_.split("=") - [Environment]::SetEnvironmentVariable($v[0], $v[1]) - } -} +$ErrorActionPreference = "SilentlyContinue" +Write-Output F|xcopy .\share\spack\qa\configuration\windows_config.yaml $env:USERPROFILE\.spack\windows\config.yaml +# The line below prevents the _spack_root symlink from causing issues with cyclic symlinks on Windows +(Get-Item '.\lib\spack\docs\_spack_root').Delete() +./share/spack/setup-env.ps1 \ No newline at end of file diff --git a/var/spack/repos/builtin.mock/packages/intel-oneapi-compilers/package.py b/var/spack/repos/builtin.mock/packages/intel-oneapi-compilers/package.py index 3ab49f1e1c..6899c2b87e 100644 --- a/var/spack/repos/builtin.mock/packages/intel-oneapi-compilers/package.py +++ b/var/spack/repos/builtin.mock/packages/intel-oneapi-compilers/package.py @@ -3,6 +3,8 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import sys + from spack.package import * @@ -23,6 +25,12 @@ def compiler_search_prefix(self): def install(self, spec, prefix): # Create the minimal compiler that will fool `spack compiler find` mkdirp(self.compiler_search_prefix) - with open(self.compiler_search_prefix.icx, "w") as f: - f.write('#!/bin/bash\necho "oneAPI DPC++ Compiler %s"' % str(spec.version)) - set_executable(self.compiler_search_prefix.icx) + comp = self.compiler_search_prefix.icx + if sys.platform == "win32": + comp = comp + ".bat" + comp_string = "@echo off\necho oneAPI DPC++ Compiler %s" % str(spec.version) + else: + comp_string = '#!/bin/bash\necho "oneAPI DPC++ Compiler %s"' % str(spec.version) + with open(comp, "w") as f: + f.write(comp_string) + set_executable(comp)