summaryrefslogtreecommitdiff
path: root/lib/spack/spack/test/llnl/util/filesystem.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/spack/spack/test/llnl/util/filesystem.py')
-rw-r--r--lib/spack/spack/test/llnl/util/filesystem.py80
1 files changed, 70 insertions, 10 deletions
diff --git a/lib/spack/spack/test/llnl/util/filesystem.py b/lib/spack/spack/test/llnl/util/filesystem.py
index 2041642dd6..eae5c732c6 100644
--- a/lib/spack/spack/test/llnl/util/filesystem.py
+++ b/lib/spack/spack/test/llnl/util/filesystem.py
@@ -13,7 +13,8 @@ import sys
import pytest
import llnl.util.filesystem as fs
-from llnl.util.symlink import islink, symlink
+import llnl.util.symlink
+from llnl.util.symlink import SymlinkError, _windows_can_symlink, islink, symlink
import spack.paths
@@ -150,7 +151,6 @@ class TestInstall:
fs.install("source/a/*/*", "dest/1")
-@pytest.mark.not_on_windows("Skip test on Windows")
class TestCopyTree:
"""Tests for ``filesystem.copy_tree``"""
@@ -189,7 +189,7 @@ class TestCopyTree:
def test_symlinks_true_ignore(self, stage):
"""Test copying when specifying relative paths that should be ignored"""
with fs.working_dir(str(stage)):
- ignore = lambda p: p in ["c/d/e", "a"]
+ ignore = lambda p: p in [os.path.join("c", "d", "e"), "a"]
fs.copy_tree("source", "dest", symlinks=True, ignore=ignore)
assert not os.path.exists("dest/a")
assert os.path.exists("dest/c/d")
@@ -231,7 +231,6 @@ class TestCopyTree:
fs.copy_tree("source", "source/sub/directory")
-@pytest.mark.not_on_windows("Skip test on Windows")
class TestInstallTree:
"""Tests for ``filesystem.install_tree``"""
@@ -275,6 +274,15 @@ class TestInstallTree:
assert not os.path.islink("dest/2")
check_added_exe_permissions("source/2", "dest/2")
+ @pytest.mark.skipif(sys.platform == "win32", reason="Broken symlinks not allowed on Windows")
+ def test_allow_broken_symlinks(self, stage):
+ """Test installing with a broken symlink."""
+ with fs.working_dir(str(stage)):
+ symlink("nonexistant.txt", "source/broken", allow_broken_symlinks=True)
+ fs.install_tree("source", "dest", symlinks=True, allow_broken_symlinks=True)
+ assert os.path.islink("dest/broken")
+ assert not os.path.exists(os.readlink("dest/broken"))
+
def test_glob_src(self, stage):
"""Test using a glob as the source."""
@@ -746,6 +754,7 @@ def test_is_nonsymlink_exe_with_shebang(tmpdir):
assert not fs.is_nonsymlink_exe_with_shebang("symlink_to_executable_script")
+@pytest.mark.skipif(sys.platform == "win32", reason="Unix-only test.")
def test_lexists_islink_isdir(tmpdir):
root = str(tmpdir)
@@ -764,12 +773,12 @@ def test_lexists_islink_isdir(tmpdir):
with open(file, "wb") as f:
f.write(b"file")
- os.symlink("dir", symlink_to_dir)
- os.symlink("file", symlink_to_file)
- os.symlink("does_not_exist", dangling_symlink)
- os.symlink("dangling_symlink", symlink_to_dangling_symlink)
- os.symlink("symlink_to_dir", symlink_to_symlink_to_dir)
- os.symlink("symlink_to_file", symlink_to_symlink_to_file)
+ symlink("dir", symlink_to_dir)
+ symlink("file", symlink_to_file)
+ symlink("does_not_exist", dangling_symlink)
+ symlink("dangling_symlink", symlink_to_dangling_symlink)
+ symlink("symlink_to_dir", symlink_to_symlink_to_dir)
+ symlink("symlink_to_file", symlink_to_symlink_to_file)
assert fs.lexists_islink_isdir(dir) == (True, False, True)
assert fs.lexists_islink_isdir(file) == (True, False, False)
@@ -781,6 +790,57 @@ def test_lexists_islink_isdir(tmpdir):
assert fs.lexists_islink_isdir(symlink_to_symlink_to_file) == (True, True, False)
+@pytest.mark.skipif(sys.platform != "win32", reason="For Windows Only")
+@pytest.mark.parametrize("win_can_symlink", [True, False])
+def test_lexists_islink_isdir_windows(tmpdir, monkeypatch, win_can_symlink):
+ """Run on windows without elevated privileges to test junctions and hard links which have
+ different results from the lexists_islink_isdir method.
+ """
+ if win_can_symlink and not _windows_can_symlink():
+ pytest.skip("Cannot test dev mode behavior without dev mode enabled.")
+ with tmpdir.as_cwd():
+ monkeypatch.setattr(llnl.util.symlink, "_windows_can_symlink", lambda: win_can_symlink)
+ dir = str(tmpdir.join("dir"))
+ file = str(tmpdir.join("file"))
+ nonexistent = str(tmpdir.join("does_not_exist"))
+ symlink_to_dir = str(tmpdir.join("symlink_to_dir"))
+ symlink_to_file = str(tmpdir.join("symlink_to_file"))
+ dangling_symlink = str(tmpdir.join("dangling_symlink"))
+ symlink_to_dangling_symlink = str(tmpdir.join("symlink_to_dangling_symlink"))
+ symlink_to_symlink_to_dir = str(tmpdir.join("symlink_to_symlink_to_dir"))
+ symlink_to_symlink_to_file = str(tmpdir.join("symlink_to_symlink_to_file"))
+
+ os.mkdir(dir)
+ assert fs.lexists_islink_isdir(dir) == (True, False, True)
+
+ symlink("dir", symlink_to_dir)
+ assert fs.lexists_islink_isdir(dir) == (True, False, True)
+ assert fs.lexists_islink_isdir(symlink_to_dir) == (True, True, True)
+
+ with open(file, "wb") as f:
+ f.write(b"file")
+ assert fs.lexists_islink_isdir(file) == (True, False, False)
+
+ symlink("file", symlink_to_file)
+ if win_can_symlink:
+ assert fs.lexists_islink_isdir(file) == (True, False, False)
+ else:
+ assert fs.lexists_islink_isdir(file) == (True, True, False)
+ assert fs.lexists_islink_isdir(symlink_to_file) == (True, True, False)
+
+ with pytest.raises(SymlinkError):
+ symlink("does_not_exist", dangling_symlink)
+ symlink("dangling_symlink", symlink_to_dangling_symlink)
+
+ symlink("symlink_to_dir", symlink_to_symlink_to_dir)
+ symlink("symlink_to_file", symlink_to_symlink_to_file)
+
+ assert fs.lexists_islink_isdir(nonexistent) == (False, False, False)
+ assert fs.lexists_islink_isdir(symlink_to_dangling_symlink) == (False, False, False)
+ assert fs.lexists_islink_isdir(symlink_to_symlink_to_dir) == (True, True, True)
+ assert fs.lexists_islink_isdir(symlink_to_symlink_to_file) == (True, True, False)
+
+
class RegisterVisitor(fs.BaseDirectoryVisitor):
"""A directory visitor that keeps track of all visited paths"""